python的一個編解碼錯誤

python的一個編解碼錯誤
發表於2012/10/24由latlontude
(1)出錯的代碼
>>> a = u"test"
>>> b = "這些一看就"
>>> c = "%s:%s"%(a,b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 0: ordinal not in range(128)

(2)沒有出錯的代碼

>>> b = u"這些一看就"
>>> a = "test"
>>> c = "%s:%s"%(a,b)
兩者有什麼區別呢?
這裏的字符串格式化默認是先把每個對象轉換爲unicode的 (這裏是按照a,b的類型進行判斷確認最終輸出字符串的編碼,如果a,b都沒有顯式聲明爲unicode,則最終轉換的類型爲編碼爲sys.getdefaultencoding()得到的字符集,否則如果a/b任意一個爲unicode類型,則最終轉換爲類型爲unicode字符串) 
轉換時調用對象的decode方法, 除非顯示聲明字符串對象爲unicode編碼,否則系統認爲默認的編碼方式是sys.getdefaultencoding(),這裏是ascii(0~128)。即轉換時會調用obj.decode(“ascii”),將obj字符串轉換爲unicode。
這樣對於1中的情形,a本身顯式聲明爲unicode,不用轉換,b會調用 b.decode(“ascii”)來轉換爲unicode對象.  對於2中的情形,b顯式聲明爲unicode,不用轉換,a會調用a.decode(“ascii”).
本文測試時,終端使用的編碼方式是utf-8,這樣2中a的utf8編碼和ascii編碼一樣,這樣轉換爲unciode就不會出錯。而1中的b的包含中文,由於終端爲utf8,實質b是utf8編碼的,其編碼的字節序中有超過0x7f的字節,這樣在利用ascii來解碼就會有不能識別的字符,這樣就會報錯“ ‘ascii’ codec can’t decode byte 0xe8 in position 0: ordinal not in range(128)”。
補充:
可以這樣設置
import sys
reload(sys)
sys.setdefaultencoding('utf8')
即使系統的默認編碼爲utf8,而非ascii碼。這樣1中的錯誤也不會出現了。
另外如果:
>>> a = "test"
>>> b = "這樣在利用"
>>> c = "%s:%s"%(a,b)
>>> print type(c)
<type 'str'>
也不會報錯,因爲a/b系統默認都是ascii的編碼。只是b由於終端設置爲utf-8才顯示爲中文。這裏就不會調用unicode來編碼了。雖然b的字符值超過了0x7f。
查看b的二進制:  顯然都是utf-8編碼的。(0xe8/0xe6….)
>>> b = "這樣在利用"
>>> import binascii
>>> binascii.b2a_hex(b)
'e8bf99e6a0b7e59ca8e588a9e794a8'

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章