python編碼問題之——Decode error - output not utf-8

iaiti發表於2015-11-23

Decode error - output not utf-8這個問題,如果用sublime text2下執行python2。就知道這個坑有多大。python3的預設是Unicode,python2的是ascii。所以搜了好多資料,總結一下。


分析各個配置的作用。

1、# -*- coding: utf-8 -*-
用於說明原始檔使用的編碼,如果沒有這個說明,原始檔中有中文字元的時候會報SyntaxError: Non-ASCII character這樣的錯誤。


2、sys.setdefaultencoding('utf-8')
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
這樣是用於設定預設的編碼格式——utf-8,由於模組載入的過程中setdefaultencoding會被刪除,所以重新載入sys
後重新設定


3、"default_encoding": "UTF-8",
在sublime的preferences的Setting-Default中,"default_encoding": "UTF-8"是配置sublime環境下的編碼


4、Python.sublime-build中的設定
{
"cmd": ["python", "-u", "$file"],
"path":"C:/Python27",
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"selector": "source.python",
"shell":"true",
"encoding": "utf-8"
}
這個設定跟sublime下執行python的編碼有關,反正"encoding": "utf-8"保證整套編碼都是utf-8
相信很多人已經和我這樣設定和配置好了,一般的解碼編碼中文沒什麼問題。
但是坑該來的還是來了。
我在及在爬取知乎的時候,發現知乎請求返回的json串中的中文用了Unicode轉換。還是出現了
Decode error - output not utf-8問題。


Decode error - output not utf-8問題

import requests
import ConfigParser
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

print sys.getdefaultencoding()
print sys.stdin.encoding
print sys.stdout.encoding

f='\u56fd\u5185\u6709\u54ea\u4e9b\u51b7\u95e8\u4f46\u6709\u7279\u8272\u7684\u65c5\u6e38\u5730\u70b9\uff1f'  
print(f.decode('unicode-escape'))

當我這樣輸出的時候,發現解碼是有問題的。現在是把Unicode轉換成中文,可以使用decode('unicode-escape')。
但是出現了Decode error - output not utf-8
最讓人蛋疼的是,有時是正常可以輸出中文——國內有哪些冷門但有特色的旅遊地點?有時報Decode error - output not utf-8錯誤。


然後後面直接在dos視窗和Eclipse的pydev環境下執行,都是正常的。


Decode error - output not utf-8問題原因

原因在哪裡呢?
注意,我寫多了兩句。

print sys.stdin.encoding
print sys.stdout.encoding

在sublime text2輸出的是None None
在Eclipse 輸出的是     UTF-8 UTF-8
在dos 輸出的是         CP936 CP936
這兩句指的是輸入和輸出的編碼。所以sublime下clt+b的執行時的這兩者編碼是未知的。


解決辦法

暫時沒有好的方法。
蹊蹺的是,我發現了這樣寫可以不會再報這個錯誤。

import requests
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

print sys.getdefaultencoding()
print sys.stdin.encoding
print sys.stdout.encoding

f='\u56fd\u5185\u6709\u54ea\u4e9b\u51b7\u95e8\u4f46\u6709\u7279\u8272\u7684\u65c5\u6e38\u5730\u70b9\uff1f'  
print type(f.decode('unicode-escape'))
f='\u56fd\u5185\u6709\u54ea\u4e9b\u51b7\u95e8\u4f46\u6709\u7279\u8272\u7684\u65c5\u6e38\u5730\u70b9\uff1f'  
print(f.decode('unicode-escape'))

輸出type是'unicode',後面的解碼不再報錯。至於為什麼這樣我也想不明白,但是sublime調了一些快捷鍵之後,用得比較爽。
如果不想這樣的話可以換個IDE。

相關文章