1. 計算機編碼歷史
ASCII Python的默認編碼,其是一種單字節的編碼。剛開始計算機世界裏只有英文,而單字節能夠表示256個不一樣的字符。最開始ASCII只定義了128個字符編碼,包括96個文字和32個控制符號,所以ASCII只使用了一個字節的後7位,最高位都爲0。每一個字符和ASCII碼的對應關係能夠查看下圖:python
EASCII 隨着計算機的發展,發現有不少西歐的字符中原ASCII中並無涵蓋,因而出現了可擴展的ASCII叫作EASCII,包含了表格符號、計算符號、希臘字母和特殊的拉丁符號,以下圖(CP437標準
):編程
除卻CP437標準外,還有ISO/8859-1(Latin-1)
標準,它繼承了CP437的128-159之間的字符,因此它是從160開始定義的,以下:函數
GBK 後來,爲了兼容中文,咱們本身弄了一套編碼叫作GB2312
,又叫作GB0
。其一共收錄了6763個漢字,同時還兼容ASCII。雖說GB2312已經涵蓋了中國大陸99.75%的漢字使用頻率,可是仍未達到100%。因而在此基礎上建立了一種叫作GBK
的編碼,其不只收錄了27484個漢字,同時還收錄了藏文、蒙文、維吾爾文等主要的少數民族文字。並且它也是兼容ASCII編碼的。在GBK中,英文字符用一個字節表示,漢字用兩個字節表示。編碼
Unicode 隨着計算機的普及,別的國家的文字諸如日文、韓文等也須要制定一套編碼規範。因而統一聯盟國際組織提出了Unicode
編碼,簡稱爲UCS
。Unicode有兩種格式:UCS-2
和UCS-4
。UCS-2就是用兩個字節編碼,一共16個比特位,這樣理論上能夠表示65536個字符,不過這還遠遠不夠。因此UCS-4則是用4個字節來表示(最高位爲0,因此實際上是31位)。spa
值得注意的是,UCS-2和UCS-4只是規定了代碼點和文字之間的關係,即全部文字都有一個代碼點。可是並無規定代碼點如何在計算機中存儲。規定存儲方式的稱爲UTF
,其中應用較多的是UTF-16
和UTF-8
。code
UTF-16 不難猜到,UTF-16是徹底對應於UCS-2的,即把UCS-2規定代碼點經過大端模式或者小端模式保存下來。UTF-16包括三種:UTF-16,UTF-16BE,UTF-16LE。blog
區分是UTF-16BE仍是UTF-16LE,須要在文件開頭以名爲BOM
的字符來代表是大端存儲仍是小端存儲,FEFF爲大端,FFFE爲小端,以下(ABC的存儲):繼承
同理,UTF-32則是對應UCS-4,再也不贅述。utf-8
UTF-8 UTF-16和UTF-32的一個缺點就是它們固定使用兩個或四個字節,這樣在表示純ASCII文件時會有不少00字節,形成浪費。因而UTF-8應運而生。ci
UTF-8用1-4個字節來表示代碼點,以下:
Unicode相對來講只是一個字符集,而UTF-8和UTF-16則是編碼規則。
Python字符編碼 前面也提到過,Python的默認編碼爲ASCII碼。在Python2.x中,有兩種字符串,分別是str
和unicode
。好比,對一個漢字「好」,用str表示,則是對應的utf-8編碼(假設是utf-8)的"\xe5\xa5\xbd",而用unicode來表示,則是u"\u597d"。str類型的字符具體編碼,跟環境有關。
在Python中,unicode經常做爲中介,字符要先解碼成unicode,才能再編碼成字符。有兩個和編碼息息相關的函數:decode()
和encode()
。它們的關係以下:
2. 文件頭編碼聲明的做用
對於文件頭部# coding: utf-8
,通常來講,有三個做用:
- 聲明代碼中會存在中文
- 在高級的IDE中,會將文件的編碼格式保存爲這行註釋指定的編碼格式
- 當Python中出現unicode字符串時,用註釋指定的編碼格式進行解碼
前面兩條都很好理解,咱們來看最後一個做用,以下(文件編碼爲utf-8):
# -*- coding: utf-8 -*- str = u'好好' # 這裏其實Python內部進行了以下操做: # 先是獲得「好好」的文件編碼(utf-8)形式,即'\xe5\xa5\xbd\xe5\xa5\xbd' # 接着因爲是unicode字符串,則用註釋中格式(utf-8)進行解碼爲unicode,即u'\u597d\u597d' print repr(str) #將獲得u'\u597d\u597d' print str.encode('utf-8') #將獲得「好好」 print str.encode('gbk') #將獲得亂碼,由於以gbk編碼後獲得的是'\xba\xc3\xba\xc3',可是print將會根據環境編碼(utf-8)來展現,則是亂碼
# -*- coding: gbk -*- str = u'好好' # 同理,先獲得「好好」的文件編碼(utf-8)形式(utf-8中漢字佔3字節,共6個字節),而後用gbk(注意)來將其解碼成unicode,因爲gbk中兩個字節爲一個漢字,因此獲得的unicode爲u'\u6fc2\u85c9\u30bd' print str.encode('utf-8') #獲得「濂藉ソ」 print str.encode('gbk') #獲得「好好」,由於通過gbk編碼後獲得'\xe5\xa5\xbd\xe5\xa5\xbd',print將其以環境編碼(utf-8)展現 str1 = '好' #其實str1以'\xe5\xa5\xbd'(即文件編碼)的形式存儲,可是Python會用註釋中的編碼形式對其進行檢查,發現這3個字節在gbk中不存在,則會報錯
3. setdefaultencoding的做用
前面說到,Python的默認編碼爲ASCII,經過這個函數這能夠修改默認編碼,通常形式爲:
import sys reload(sys) sys.setdefaultencoding('編碼格式') #默認是ASCII
設置這個編碼格式主要應用是在如下場景中:
# -*- coding: utf-8 -*- str = '好好' print repr(str.encode('utf-8')) # 其實這裏Python是這樣執行:str.decode('ascii').encode('utf-8') # 先解碼成unicode,因爲ascii不支持中文,故會報錯 print repr(str.decode('utf-8').encode('gbk')) # 先用utf-8解碼爲unicode,獲得u'\u597d\u597d' # 而後用gbk格式編碼,獲得'\xba\xc3\xba\xc3' # print以utf-8(環境編碼)展現,獲得亂碼
因此說,默認編碼的優先順序爲:decode顯式設置 > setdefaultencoding設置 > ascii編碼
4. 建議
爲了減小Python編程中的編碼出錯,我總結了一下幾個建議:
-
注意系統環境編碼,儘可能讓文件編碼和系統環境編碼一致;
-
註釋的編碼格式最好和文件編碼格式同樣;
-
decode採起的編碼和encode採起的編碼需一致,否則通常會出錯。