python3的編碼問題


Python3對文本(str)和二進制數據(bytes)作了更為清晰的區分。

文本默認是以Unicode編碼(python2默認是ascii),由str類型表示,二進制數據則由bytes類型表示。

str='中文ENGLISH'

str是文本類型,即str類型

>>> str.encode('utf-8')
b'\xe4\xb8\xad\xe6\x96\x87ENGLISH'
>>> str.encode('gb2312')
b'\xd6\xd0\xce\xc4ENGLISH'
>>> bytes(str,'utf-8')
b'\xe4\xb8\xad\xe6\x96\x87ENGLISH'

bytes()函數同str.encode(),即把str類型編碼為bytes類型

>>> b'\xe4\xb8\xad\xe6\x96\x87ENGLISH'.decode('utf-8')
'中文ENGLISH'

解碼過程,即把bytes數據轉化為str

>>> b'\xe4\xb8\xad\xe6\x96\x87ENGLISH'.encode('utf-8')
Traceback (most recent call last):
  File "<pyshell#42>", line 1, in <module>
    b'\xe4\xb8\xad\xe6\x96\x87ENGLISH'.encode('utf-8')
AttributeError: 'bytes' object has no attribute 'encode'

不能把bytes數據繼續編碼為bytes

>>> '中文ENGLISH'.decode('utf-8')
Traceback (most recent call last):
  File "<pyshell#44>", line 1, in <module>
    '中文ENGLISH'.decode('utf-8')
AttributeError: 'str' object has no attribute 'decode'

也不能把str數據繼續解碼為str

即編碼過程是從str到bytes,解碼過程是從bytes到str。

>>> b'\xe4\xb8\xad\xe6\x96\x87ENGLISH'.decode('gb2312')
Traceback (most recent call last):
  File "<pyshell#45>", line 1, in <module>
    b'\xe4\xb8\xad\xe6\x96\x87ENGLISH'.decode('gb2312')
UnicodeDecodeError: 'gb2312' codec can't decode byte 0xad in position 2: illegal multibyte sequence

上面是把以utf-8編碼的bytes以gb2312的方式解碼,結果出錯了,因為0xad沒有對應的gb2312編碼

如果想知道一串bytes碼是以何種unicode編碼方式編碼的,該如何呢?這個其實是無法百分之百確定的,不然的話亂碼就不會發生了。

第三方庫chardet,使用函數detect可以“猜”出編碼方式。

from chardet import detect
>>> detect(b'\xe4\xb8\xad\xe6\x96\x87ENGLISH') {'confidence': 0.7525, 'encoding': 'utf-8'}

這里置信0.7525,可以簡單理解為概率0.7525,這里只有兩個中文字符,如果bytes足夠長,那么置信肯定更高

>>> detect(b'\xe6\x88\x91\xe6\x98\xaf\xe4\xb8\xad\xe6\x96\x87\xe6\x88\x91\xe7\x9c\x9f\xe7\x9a\x84\xe6\x98\xaf\xe4\xb8\xad\xe6\x96\x87')
{'confidence': 0.99, 'encoding': 'utf-8'}

這里有10個中文字符,結果置信就是0.99了

__________________________________________________________________________________

從txt文件讀取的問題

有兩個文件ansi.txt和utf8.txt,分別保存為ansi編碼和utf-8編碼,里面都是‘中文ENGLISH’

>>> f_ansi=open(r'd:\ansi.txt','r')
>>> f_ansi.read()
'中文ENGLISH'
>>> f_utf8=open(r'd:\utf8.txt','r')
>>> f_utf8.read()
'鍩誇腑鏂嘐NGLISH'
>>> f_utf8=open(r'd:\utf8.txt','r',encoding='utf-8')
>>> f_utf8.read()
'\ufeff中文ENGLISH'
#帶BOM的utf8

記事本的ansi編碼為系統本地編碼,我的是gbk,所以ansi.txt的編碼方式是gbk

open()函數的encoding參數默認是本地編碼,也就是gbk,所以直接打開讀取ansi.txt是可以的

直接打開utf8編碼的txt會以gbk的解碼方式讀取,所以會出現亂碼

驗證一下

>>> '鍩誇腑鏂嘐NGLISH'.encode('gbk').decode('utf-8')
'\ufeff中文ENGLISH'

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM