標籤:

python編碼錯誤:UnicodeDecodeError: utf8 codec cant decode

這個是在寫hive的map腳本時遇到的,基本情況如下:

map文件中調用了其他同學的公用函數,在hive腳本中運行時,輸出報錯。但是,如果單獨運行python,並輸出到文件,就沒有錯誤了,感覺異常的詭異,其中hive報錯如下:

Traceback (most recent call last): File "search_map_script_py", line 114, in <module> dataStreamProcess(line) File "search_map_script_py", line 108, in dataStreamProcess print "%s %s %s %s %s %s %s %s %s %s" % (pbrand, ptype, psize, res, softv, organic, appfrom, searchtype, cuid, search_tm) UnicodeDecodeError: "ascii" codec can"t decode byte 0xe5 in position 5: ordinal not in range(128)

於是在map腳本中添加sys模塊,設定了輸出的環境為utf8:

import sysreload(sys)sys.setdefaultencoding("utf-8")

但是,初步的問題解決後,不部分時間腳本運行正常,但是,時而出錯。單獨運行python,並輸出到文本,一切正常。其中hive腳本報錯如下:

Traceback (most recent call last): File "searchBox_user_map_script_py", line 212, in <module> dataStreamProcess(line) File "user_map_script_py", line 201, in dataStreamProcess print "%s %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s" % (baiduapp_uid, imei, actionType, os, os_ver, net, resolution,event_country,event_province,event_city,softv,app_from, loc_country, loc_province, loc_city, phoneBrand, phoneType, phoneSize, netOper, year, month, day, tstamp) UnicodeDecodeError: "utf8" codec can"t decode byte 0x80 in position 25: invalid start byte

以上問題出現後,糾結了大概一周左右,借下面博主的文章,順利解決:

print "%s %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s" % (baiduapp_uid, imei, actionType, os, os_ver, net, resolution,event_country,event_province,event_city,softv,app_from, loc_country, loc_province, loc_city, unicode(phoneBrand).encode(『utf-8』), unicode(phoneType).encode(『utf-8』), phoneSize, netOper, year, month, day, tstamp

其中,之前已經判斷出錯欄位為phoneBrand, phoneType。

--------------------以下為博主原文-----------------------------

【已解決】Python腳本語法錯誤:SyntaxError: (unicode error) "utf8" codec can"t decode byte 0xc0 in position 0: invalid start byte

【背景】

一個python腳本,運行的時候出錯了:

D: mpWordPressOthers o_wphi-baidu-mover_v2>hi-baidu-mover_v2011-12-22-office.py -fhttp://hi.baidu.com/recommend_music/blog/item/de233143bd84211a72f05deb.html -l 1File "D: mpWordPressOthers o_wphi-baidu-mover_v2hi-baidu-mover_v2011-12-22-office.py", line 869cat_no_unicode = opt_no_unicode.replace(u"類別:", "")SyntaxError: (unicode error) "utf8" codec can"t decode byte 0xc0 in position 0: invalid start byte

【解決過程】

1.覺得很奇怪的一點是,這個腳本,一直是可以正常運行的,怎麼突然就出現了語法錯誤了。

然後發現是帶有中文的代碼,會出現錯誤。

第一反應是,可能是安裝了那個python的Python Imaging Library (PIL)庫,然後影響了當前的python 2.7.2版本的語法了,影響成為類似於python 3.x的語法了。

因為之前試過,python 3.x版本中,對於上述寫法,即u加上中文,比如:

u『這是中文』,是不支持的。而python 2.x的語法是支持的,表示這個字元是unicode的字元,會自動處理編碼,成為unicode變數的。

所以,就是嘗試了,卸載掉之前安裝的PIL-1.1.7.win32-py2.7.exe,結果問題依舊。

2.對應著當前這個python腳本,之前還有一個版本,裡面也有同樣的這部分代碼,結果卻是,那個腳本可以正常執行,這個腳本無法執行,出現這個SyntaxError: (unicode error)錯誤,所以更加異怪了。

本來想找個beyondcompare來比較兩個腳本之前到底有哪些區別的,結果由於暫時不方便下載安裝使用beyondcompare,只好作罷。

3.重新安裝了python 2.7.2,問題依舊。

4.重啟電腦,問題依舊。

5.後來,把上述代碼中中文字元前綴的u,改為函數unicode加上中文字元,即:

cat_no_unicode = opt_no_unicode.replace(unicode("類別:"), "")

結果,就可以正常執行了,沒有了這個語法錯誤。

6.然後才突然想到,是不是腳本文件本身的編碼不匹配,一去查看當前所用的notepad++中的當前腳本文件所用的編碼,果然,用的是默認的ANSI,而不是utf-8的編碼,所以,u"類別:",無法識別,而去notepad+中,格式->轉為utf-8編碼,後,再保存文件,再去運行腳本,就可以支持u"類別:"了。

當然,對應的unicode(「類別:」)這樣的做法,起始是最安全的,其不會受到你當前python腳本文件所用編碼的影響。

【總結】

1。如果python中所要處理的字元串中包含中文,那麼最好要搞懂所用字元的編碼,是gbk/gb2312/gb18030,還是utf-8,否則容易出現亂碼,以及此處的語法錯誤。

而為了保險起見,最好用unicode("中文字元")的方式,來使用,操作這些中文字元。

當然,如果你自己需要,自己也知道,那最好unicode("中文字元").encode("utf-8")的方法,把其轉為utf-8的格式,這個編碼最通用。

2.notepad++新建的文件,也最好使用比較通用的utf-8的格式來存儲文件,而不要用默認的ANSI,否則其中的中文,會由於ANSI不支持,而默認用你本地語言,比如我此處的GBK,去編碼,這樣容易出現一些編碼類的錯誤。


【後記1】

本來覺得上面的理解是完全正確的。

結果證實了,上面的理解,是錯誤的。。。

實際的例子是:

如果用unicode("下午").encode("utf-8"),然後python腳本可以執行通過,但是結果卻不對,無法和我從網頁中抓取到的utf-8的「下午「相匹配,導致代碼運行結果不是我們想要的。

而只有通過u」下午「.encode("utf-8")得到的結果,才和我網頁中抓取到的utf-8的」下午「相等,代碼才可以按照預期的結果去執行。

所以,結論是:

【總結】

1.python腳本文件所用編碼,如果可以,最好用utf-8.

2.腳本中,用到的中文字元,具體是unicode(」中文「).encode("utf-8"),還是u」中文」.encode("utf-8"),你要自己嘗試,才知道結果如何。至少我這裡的,是後者,程序執行結果才是對的。


【後記2】

1.經過測試:

此處我從網頁抓取的中文字元moring_afternoon_zhCN,isinstance(moring_afternoon_zhCN, unicode)的結果,是False,即不是unicode字元。和之前介紹的,網頁內容被beautifulsoup處理後,就自動轉為utf-8這點,所不一致了。暫未搞懂是啥原因。

而且實際一個是utf-8的字元和這個字元比較:

afternoon_zhCN_utf8 = u"下午".encode("utf-8") #if unicode(moring_afternoon_zhCN).encode("utf-8") == afternoon_zhCN_utf8: if unicode(moring_afternoon_zhCN).encode("utf-8") == unicode("下午").encode("utf-8") : # this line can not excute!!! hour = str(int(hour) + 8)

結果也會出錯的:

File "D: mpWordPressOthers o_wphi-baidu-mover_v2hi-baidu-mover_v2011-12-22-office.py", line 1169, in parseAndSetEntryDatetime if unicode(moring_afternoon_zhCN).encode("utf-8") == unicode("涓嬪崍").encode("utf-8") : # this line can excute, but result is worng !!!UnicodeDecodeError: "ascii" codec can"t decode byte 0xe4 in position 0: ordinal not in range(128)

2. 上面的isinstance(u"下午".encode("utf-8"), unicode)結果為False,即不是unicode字元,這點需要注意一下的。因為本身u"下午"是unicode字元,屬於unicode類型,被轉換編碼encode("utf-8")後,就是普通的字元,屬於str類型了。

轉載自:http://againinput4.blog.163.com/blog/static/1727994912011112224749861/


推薦閱讀:

兒童編碼又一項世界紀錄誕生!
iOS KVO crash 自修復技術實現與原理解析
URL編碼與解碼
字元,位元組和編碼
DRGs應用下,疾病編碼常見問題有哪些?

TAG:錯誤 | 編碼 |