如果說在Python2中處理字符編碼很蛋疼的話,如果幻想著python3不那么蛋疼,那么我只想說,你想多了,好不容易在python2中把字符編碼的問題搗騰清楚了,但是換成python3,它會將之前的體系重新構建,使得之前的知識體系不能很好的運用,只能重新來構建。感覺是從一個坑跳到了另外一個坑,下面來看看這個令人頭疼的python編碼問題。
python2中的編碼處理
python2中將ASCII 碼作為默認編碼方式,對中文處理很不友好。
>>> import sys >>> sys.getdefaultencoding() 'ascii'
關于 GBK 和 UTF-8,概念性的東西就不解釋了,網上一搜便知,這里主要是來說明一下,將一個 GBK 編碼的字符串轉換成 UTF-8 編碼,只需要通過 Unicode 來轉換
>>> s = '楊' >>> s '\xd1\xee' >>> type(s) <class 'str'> >>> print s 楊 >>> su = s.decode('gbk') >>> su u'\u6768' >>> sutf8 = su.encode('utf-8') >>> sutf8 '\xe6\x9d\xa8' >>> print sutf8 鏉?
其實就是將 unicode 作為一個中轉站,將各種編碼轉換(decode)成unicode 使用 s.decode(chaset) ,然后再將unicode編碼的字符串轉換(encode)成想要的編碼 s.encode(chaset)。
其實這么看在python2中的字符編碼問題也不是很復雜,主要是要弄清楚字符串本身是什么編碼即可。有一個庫可以檢測字符編碼,chardet ,使用chardet.detect(str) 來檢查字符串編碼,注意,它這里給出的只能做為參考,并不能很準確的給出編碼,所以他的返回值中會有一個 confidence 的值,如果值是1.0,說明它100%的肯定是這個編碼。
python3中的編碼處理
再來看看python3的編碼處理,python3中將unicode合并成了str,已經沒有unicode這種類型了。
>>> s = '楊' >>> type(s) <class 'str'> >>> su = u'楊' >>> type(su) <class 'str'> >>> s '楊' >>> su '楊'
可以看出它們都是 str 類型。 那么如何在python3中將一個GBKx編碼的字符串轉成utf-8呢? python3中有一種全新的數據類型 bytes ,它表示二進制字節數據,初始化是在字符前加 b ,bytes 類型可以是 ASCII范圍內的字符和其它十六進制形式的字符數據,但不能用中文等非ASCII字符表示。
>>> b = b'a' >>> b b'a' >>> type(b) <class 'bytes'> >>> a = 'a' >>> type(a) <class 'str'> >>> b = b'楊彥星' File "<stdin>", line 1 SyntaxError: bytes can only contain ASCII literal characters.
雖然在python3中不能直接的以 b = b'楊彥星' 來初始化bytes,但是卻可以用在python2中得到的十六進制表示來初始化
在python2中
>>> '楊彥星' '\xd1\xee\xd1\xe5\xd0\xc7' >>>
在python3中
>>> s = b'\xd1\xee\xd1\xe5\xd0\xc7' >>> print(s) b'\xd1\xee\xd1\xe5\xd0\xc7' >>> type(s) <class 'bytes'> >>> ss = s.decode('gbk') >>> ss '楊彥星' >>> type(ss) <class 'str'> >>>
熟悉的中文又出現了,有了str 那么就可以將其轉換成對應的編碼了
>>> ss.encode('utf-8') b'\xe6\x9d\xa8\xe5\xbd\xa6\xe6\x98\x9f'
依然不知道它顯示的是個啥,但是你可以明確的知道,它在python3里就是楊彥星這個字符串的utf-8編碼
>>> s8 = b'\xe6\x9d\xa8\xe5\xbd\xa6\xe6\x98\x9f' >>> s8.decode('utf-8') '楊彥星'
最后使用代碼做個總結
結果如下
由于今日頭條上發的文章對于代碼排版不太方便,所以我將代碼片段都使用了截圖的方式,想要復制代碼請點擊 "了解更多"來查看原文或者微信搜索公眾號"序語程言"