令人頭疼的Python編碼問題

前言

你是否在編寫Python代碼時,老是遇到UnicodeDecodeError/UnicodeEncodeError錯誤,無從下手。或者是打印一串字符串,確是亂碼,搞人心態。

別慌,本文將從編碼的前世今生講解,讓你對編碼有個深刻了解,以便後期對Python編碼問題進行分析和解決。

字符編碼的前世今生

大家都知道,電腦本身是不認識字符的,只認識0和1。所以說,電腦的字符需要通過轉換爲0和1才能被電腦所識別,其實,讓字符轉換爲被電腦識別的01數字的過程,就是字符編碼。

當然,字符編碼需要定義一套標準,不然電腦就沒法準確識別字符了。標準這東西大家都懂的,大部分都是國外先定標準,國內再定,而且很難做到統一。

基於英文的ASCII碼,由一個字節表示,一個字節就是8bit,顧名思義就是最大能代表256個字符(2的8次方)。256個字符對付英文綽綽有餘,但是中國文字這麼多,顯然 ASCII碼就不適用了。中國人定製了GBK,但是每個國家都自己定製,那就很難統一。

這時候萬國碼Unicode編碼出現,採用了兩個字節進行編碼,那現在問題也來,就是英文字母一個字節就能搞定,現在都要兩個字節,那不是很浪費內存嗎。可變長度編碼UTF-8出現,解決了這個問題,字母就用一個字節,複雜的字符就用兩個字節。

總結下,Unicode編碼佔用空間,但運行速度快,UTF-8恰恰相反,所以內存中用Unicode編碼,而存儲用UTF-8,這個大家要好好記着。

Python3編碼

首先,Python3默認編碼爲utf-8。

import sys
print(sys.getdefaultencoding())

# utf-8

然後,Python分爲str和bytes兩種數據類型,文本字符爲str,str能表示Unicode 字符集中所有字符,bytes代表二進制數據。

a = 'a'
b = '羅攀'
print(type(a),type(b))

c = b'\xe7\xbd\x97\xe6\x94\x80'
print(c,type(c))

#<class 'str'> <class 'str'>
#b'\xe7\xbd\x97\xe6\x94\x80' <class 'bytes'>

encode 與 decode

之前的錯誤分爲UnicodeDecodeError和UnicodeEncodeError,其實就是編碼和解碼錯誤。

簡單的說,從字符轉爲電腦能識別的01,就是編碼,01轉換爲字符,就是解碼。這裏的編碼和解碼必須一致,不然就會報錯。

str 與 bytes 之間的轉換就是用 encode 和從decode 方法。

a = '羅攀'
print(a.encode('utf-8'))
print(a.encode('utf-8').decode('utf-8'))
print(a.encode('gb2312').decode('utf-8'))

# b'\xe7\xbd\x97\xe6\x94\x80'
#羅攀
#Traceback (most recent call last):
#  File "/Users/luopan/Python練習/編碼問題.py", line 25, in #<module>
#    print(a.encode('gb2312').decode('utf-8'))
#UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc2 in position 0: invalid continuation byte

案例分析

例如,我在本地新建一個txt,編碼爲utf-16。

如果我們直接讀取文件,就會報錯,那是因爲python默認編碼爲utf-8。

所以我們需要指定編碼即可。

我們下期再見~

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