python连接mysql报错:'latin-1' codec can't encode characters

python连接mysql数据库进行查询时, 遇到以下报错: UnicodeEncodeError: 'latin-1' codec can't encode characters in position 40-41: ordinal not in range(256) 很明显提示了是字符编码的问题

发生以上问题, 是因为我在sql语句中出现了中文, 在拿到db游标对象之后, 去执行sql的时候的报错

排查数据库字符编码

登录MySQL数据库, 执行以下SQL语句执行查询:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
+--------------------------+--------------------+
| Variable_name | Value |
+--------------------------+--------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| collation_connection | utf8mb4_unicode_ci |
| collation_database | utf8mb4_unicode_ci |
| collation_server | utf8mb4_unicode_ci |
+--------------------------+--------------------+
10 rows in set (0.00 sec)

经过查询, 发现mysql数据库本身已是 utf8 的字符编码

分析可能的原因:

mysql一般有三段配置, 分别是: [mysql] [clinet] [mysqld]

  • [mysql] 对其他远程连接的mysql客户端的配置, 例如在其他服务器执行mysql -h -u -p或使用代码进行连接
  • [client] 对本地的mysql客户端的配置, 例如在本地执行mysql -u -p
  • [mysqld] 对mysql服务进行配置

有可能mysql配置文件中的[mysql]下没有配置 default-character-set = utf8mb4, 导致远程客户端连接到服务器端后, 没有获得服务端声明的字符编码, 而使用客户端默认带的字符编码进行连接, 如果是这种情况, 可以在mysql服务端更改配置文件并重启mysql服务, 如果你不想重启数据库, 可以显示地在mysql客户端声明使用的字符编码

解决pymysql字符编码问题

1
2
3
4
5
6
7
import pymysql

db = pymysql.connect("localhost","root","123","mysql", charset="utf8")
cursor = db.cursor()

sql = "select Host, User from user where User='中文';"
cursor.execute(sql)

解决方法很简单, 只需要在创建数据库连接对象的时候, 显示地声明字符编码就可以了 charset="utf8"

注意: 如果你的MySQL服务器的字符编码使用的是utf-8 的话, 你需要声明你的连接对象的字符编码也是 utf-8

如果你的MySQL服务器的字符编码使用的是utf8mb4 的话, 相对应的, 你应该声明自己客户端的字符编码是 utf8mb4