一、环境及问题描述
1. 环境
操作系统:win10,64bit。
python版本:2.7.15
mysql版本:5.7.23
2. 问题描述
使用python从某个数据文件读取数据,处理后,用MySQLdb去连接数据库表并插入数据,此时报错:
OperationalError: (1366, "Incorrect string value..."
网上可以查到是编码问题:
出现这个异常是mysql问题,而非python的问题,这是因为mysql的字段类型是utf-xxx, 而在mysql中这些utf-8数据类型只能存储最多三个字节的字符,而存不了包含四个字节的字符。
因为之前的数据库的字符集是utf8,所以需要转为utf8mb4编码。
不幸的是,我装的mysql版本很老,是5.4的版本,而utf8mb4编码在5.5.3后才支持,于是只能重装mysql,重新装的是5.7.23的版本。
二、关于utf8mb4编码
MySQL在5.5.3版本之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode。其实,utf8mb4是utf8的超集,理论上原来使用utf8,然后将字符集修改为utf8mb4,也会不会对已有的utf8编码读取产生任何问题。当然,为了节省空间,一般情况下使用utf8也就够了。
既然utf8应付日常使用完全没有问题,那为什么还要使用utf8mb4呢? 低版本的MySQL支持的utf8编码,最大字符长度为 3 字节,如果遇到 4 字节的字符就会出现错误了。
三个字节的 UTF-8 最大能编码的 Unicode 字符是 0xFFFF,也就是 Unicode 中的基本多文平面(BMP)。也就是说,任何不在基本多文平面的 Unicode字符,都无法使用MySQL原有的 utf8 字符集存储。
三、问题解决
1. 数据库编码修改
修改my.ini的内容:
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
将数据库和已经建好的表也转换成utf8mb4:
ALTER DATABASE db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
更改表编码:
ALTER TABLE TABLE_NAME CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
重启mysql服务。
如果这个时候已经解决问题,可以不用往下看了。
否则,可以看看下面的思路能否为你提供一点想法。
我的情况是依旧没有解决问题。
2. 从读取文件的编码入手
发现数据文件的编码是gb2312,所以读取一行内容后需要转为unicode然后再转为utf8:
line = line.decode('gbk').encode('utf-8')
(奇怪的是用’gb2312’就不行)
至此问题解决。
所以可以看出实际上我遇到的问题只是读取的编码在写入mysql的时候不能识别而已,后面我新建一个表,默认编码为utf8,也能正常插入,这也验证了这个想法。
四、参考
1. python插入数据到mysql时报错:mysql
2. utf8mb4与utf8的区别
3. 更改MySQL数据库的编码为utf8mb4
(完) |