Python程式設計:Python2編碼問題與pymysql查詢結果亂碼解決
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
推薦使用後者
參考
執行程式碼檔案,發現輸出正常了
((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
"""