订阅专栏
Python2编码一直是个让人头疼的问题,能够让一个充满激情的新手,从刚安装完python解释器到放弃。
我就曾经放弃过,后来又拿了起来,真是一波多折。
so,如果可能就尽量使用Python3吧
下面我就python2通过pymysql处理查询结果为例说明
要查询的数据表(包含中文)
mysql> use demo mysql> select * from names limit 3; +----+--------+------+ | id | name | age | +----+--------+------+ | 1 | 大红 | 24 | | 2 | 大壮 | 24 | | 3 | 秀英 | 24 | +----+--------+------+
python2原始代码
from collections import namedtuple import pymysql db = pymysql.Connect( host="localhost", user="root", password="123456", database="demo", port=3306 ) sql = "select name, age from names limit 3" cursor = db.cursor() cursor.execute(sql) rows = cursor.fetchall() cursor.close() db.close() print(rows) Row = namedtuple("Row", ["name", "age"]) rows = map(Row._make, rows) for row in rows: person = "{}{}".format(row.name, row.age) print(person)
1、SyntaxError: Non-ASCII character
看着好好的代码,莫名其妙的来个语法错误SyntaxError: Non-ASCII character
SyntaxError: Non-ASCII character '\xe5' in file text.py on line 56, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
根据报错提示的链接: http://python.org/dev/peps/pep-0263/
打开后发现需要在文件头加文件编码说明
# coding=utf-8
或者
#!/usr/bin/python # -*- coding: utf-8 -*-
2、中文变成了?
添加完文件编码后,继续运行代码,代码文件中有print(rows)和print(person)打印出来的内容分别是:
(('??', 24), ('??', 24), ('??', 24)) ??24 ??24 ??24
what? 查看pymysql.Connect 的源码,发现有一个参数charset字符集,那么添加一个字符编码试试
db = pymysql.Connect( host="localhost", user="root", password="123456", database="demo", port=3306, # 添加字符编码 charset="utf8" )
3、UnicodeEncodeError
添加完编码字符集参数后,运行又报错了!
((u'\u5927\u7ea2', 24), (u'\u5927\u58ee', 24), (u'\u79c0\u82f1', 24)) Traceback (most recent call last): File "text.py", line 37, in <module> person = "{}{}".format(row.name, row.age) UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
发现print(rows)已经打印了,而且没有?,前面带u,说明是unicode字符
报错代码是:person = "{}{}".format(row.name, row.age),使用format格式化报错
明明已经在文件开头指定了文件的编码是utf-8了,怎么还是说unicode呢?
百思不得其解,经过百度,google,发现只用添加以下代码就行:
import sys reload(sys) sys.setdefaultencoding("utf-8")
或者
from __future__ import unicode_literals
推荐使用后者
参考
1.https://*.com/questions/3828723/why-should-we-not-use-sys-setdefaultencodingutf-8-in-a-py-script
运行代码文件,发现输出正常了
((u'\u5927\u7ea2', 24), (u'\u5927\u58ee', 24), (u'\u79c0\u82f1', 24)) 大红24 大壮24 秀英24
当然,直接打印整个元组对象是不能直观的看到内容的,打印出来的是unicode码,而python3就可以
总结
好了,一路过来解决3个编码问题,都需要设置编码为utf-8
报错 |
解决 | 示例 |
SyntaxError: Non-ASCII character | 文件编码 | # -*- coding: utf-8 -*- |
中文变成了? |
数据库连接编码 | charset="utf8" |
UnicodeEncodeError | 引入py3的新特性 | from __future__ import unicode_literals |
注意,pymysql的编码设置charset="utf8"中间没有-
python2中的编码问题基本可以用以下两行代码解决
# -*- coding: utf-8 -*- from __future__ import unicode_literals
给出最后的完整代码
# -*- coding: utf-8 -*- # @Date : 2018-12-20 # @Author : Peng Shiyu from __future__ import unicode_literals from collections import namedtuple import pymysql db = pymysql.Connect( host="localhost", user="root", password="123456", database="demo", port=3306, charset="utf8" ) sql = "select name, age from names limit 3" cursor = db.cursor() cursor.execute(sql) rows = cursor.fetchall() cursor.close() db.close() print(rows) Row = namedtuple("Row", ["name", "age"]) rows = map(Row._make, rows) for row in rows: person = "{}{}".format(row.name, row.age) print(person) """ ((u'\u5927\u7ea2', 24), (u'\u5927\u58ee', 24), (u'\u79c0\u82f1', 24)) 大红24 大壮24 秀英24 """