首先描述下問題:
在使用python計算出結果后將結果插入到mysql過程中,報如下錯誤。原因很好定位就是編碼的問題。那么到底是編碼哪里出了問題了呢?
報錯如上:
排查順序:
第一:python的編碼
自己的代碼,發現打開的時候的確已經制定了編碼?那么問題應該不是在python的編碼問題。
同時采用:
打印出word[5] 又發現會報錯 ASCii 不識別等錯誤。於是再這里糾結了很久很久。終於把打印問題解決了。
解決辦法:如果要打印出正常的中文,在程序開頭加上這么一段代碼 即可:
python 腳本
import io import sys from urllib.request import urlopen sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')
注意:上面的代碼,僅僅能解決在打印的時候打印出中文。
如果沒有上面的代碼,會報如下錯誤:
python報錯代碼:
Traceback (most recent call last): File "/data/codes/run.py", line 46, in <module> pre(sys.argv[2], sys.argv[3], sys.argv[4], clean_run=False, **optional) File "/data/codes/matrix/preprocess.py", line 30, in pre preprocess(job.input_file(), timestamp) File "/data/codes/matrix/job/preprocess.py", line 23, in preprocess for record in load_data(filename): File "/data/codes/matrix/data/DataLoader.py", line 75, in load_data print(words[3]) UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
總之:你會發現不是python的錯誤,而應該是插入到mysql里面發生了錯誤,那么我們去找mysql的編碼問題問題。
第二:Mysql數據庫的編碼
我們都知道,mysql編碼的時候默認是 lati1編碼。但是更多時候我們會把他換成utf-8。
於是普遍的,我們在建完數據庫,會做編碼的修改,例如:
mysql代碼:
set character_set_client=utf8; set character_set_results=utf8; set character_set_connection=utf8; set character_set_database=utf8;
但是,我想很鄭重的告訴你,你以為這樣就真的萬事大吉了,你以為這樣再出現問題就不是mysql的問題了。
你會想,我都設置成了 utf-8 還會出現什么問題呢?
接下來我們看看,設置完上面之后我的數據庫中的的一個表
看到么?里面的表的編碼還是latin1。
於是,我們得出結論是,如果你在建立表之后才修改myslq 的編碼,那么原來建的邊的編碼不會發生變化。要讓其變化必須進行更加確切的編碼指定,例如用下面的語句
:
mysql代碼:
alter table BETWEENNESS character set utf8;·
這個時候你可能會認為這樣就完成了,but,python的運行下,錯誤仍然會繼續報錯。
我們這個時候再看看數據庫表的編碼類型:
惡心不惡心,你把表的編碼都改好了,卻發現字段的編碼還是默認的Latin1。親愛的latin1你是有多么的愛我,舍不得我。
從上面的報錯,我們能看到,主要原因是我的 ‘semantic’字段報的錯。
於是下面這個代碼解決了問題:
mysql代碼:
alter database matrix character set utf8; alter table BETWEENNESS change semantic semantic varchar(32) character set utf8 not null; alter table BETWEENNESS character set utf8;
直到這個時候,問題徹底解決了。latin1終於不見了。
總結: 在你需要的數據庫建立之前就將所有的編碼都設置mysql 代碼
set character_set_client=utf8; set character_set_results=utf8; set character_set_connection=utf8; set character_set_database=utf8;
一旦你已經在為做任何編碼改動的時候把表和數據庫已經建立好的話,那么執行上面的代碼后,前面建立的表的各種編碼似乎改變好像要看運氣,哈哈。嚴格的說不是運氣,我對數據庫不是很熟悉,所以不知道具體原因。
但是一旦你發生了上面的問題。就是先建立了數據庫和表,需要更改編碼的時候。請將以前建立的數據庫和表,通過確切的具體的方式把他們的編碼修改過來。
例如:
alter table <表名> character set utf8; alter table <表名> change <字段名> <字段名> <類型> character set utf8; alter table user change username username varchar(20) character set utf8 not null;
分享一個關於改變mysql'編碼的文章:http://www.cnblogs.com/shootercheng/p/5836657.html
-----------------------------------------------------------------------------華麗麗的分割線------------------------------------------------------------------------------------------------------------
說說感想:
這個小的問題,我折騰了兩天,感覺有一肚子的氣要說出來,真正寫出來的時候覺得問題就是那么簡單,高手也許半個小時就解決了,只是覺得自己很笨。
第一天和第二天的一半時間都以為是python的問題,在找各種python編碼轉中文的問題,感覺百度的文章都被我找遍了。找的過程中還考慮了python版本的問題,發現有些函數在2.7使用,3.5就不適用了。例如下面的代碼:
import sys reload(sys) sys.setdefaultencoding('utf8')
3.5版本的會告訴你 不認識reload函數
回到前面,如果要打印中文就加上如下腳本
python 腳本 import io import sys from urllib.request import urlopen sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')
如果讀文就加上:
open(filename, 'r', encoding="utf8") as reader:
我們再回到mysql編碼:
總之還是要細心,當python和mysql對接的時候請注意檢查:
1. 確保數據庫編碼為 `utf-8`
2. 確保數據庫表的編碼為`utf-8`
3. 確保數據庫字段編碼為 `utf-8`
4.程序連接數據庫指定編碼:`MySQLdb.connect("localhost","root","***","Data",charset='utf8')`
5.文本的編碼問題也應該統一。
參考網址:http://blog.csdn.net/shomy_liu/article/details/47681893
關鍵詞“細心”。