前兩天理解了unicode、utf-8、gb2312這些編碼之間的關係以後,今天終於弄明白了在python裡面的編碼問題。我們在寫python指令碼時如果有中文的字串,在執行的時候有可能會報錯也有可能會出現亂碼。一般加上# -*- coding:utf-8 -*-就不會報錯了,但是還可能有亂碼問題,而且同樣的程式碼在不同的編輯器中得出的結果還有可能不一樣,你是否也遇到過這些問題而且理不清頭緒?希望我的講解能讓你對這個問題有一定的理解。
對於python的一個指令碼來說有三種編碼:
1. 指令碼檔案的編碼
指令碼儲存時的編碼格式,不同的編輯器採用的格式不同會造成一定的混亂,一般是utf-8或者cp936(windows上)
2. python解析器的編碼
python預設使用ascci編碼,所以如果你的指令碼中出現了中文,用ascci編碼區解析一定會出錯,因為ascci不沒有utf-8,cp936裡面的中文字元的。所以你要在指令碼的第一行加入# -*- coding:utf-8 -*-註釋來通知python解析器使用utf-8,但是這個只是通知一下python而不是真的用utf-8的編碼區解析這裡的中文字串。例如,你寫了一個指令碼儲存的編碼是cp936的,如果不加入註釋一定會在執行時報錯,因為ascci不包括cp936裡面的字元,而你寫了第一行的註釋就不會報錯了因為utf-8中有這個字元,但是字元的含義未必是那個中文,它僅僅是處理一下。這裡有個地方需要注意如果你的指令碼儲存時的編碼是utf-8的就不需要第一行的註釋,python會正確識別。我個人理解是python只識別utf-8和ansi兩種格式的檔案,ansi格式的需要明確指出coding,否則python預設使用ascci來處理
3. 執行指令碼的環境的編碼
如果執行環境的編碼格式與指令碼檔案的格式相同就正確顯示,不同就是亂碼,因為執行環境會進行解碼
還是看看程式碼吧:
# -*- coding:utf-8 -*- #如果沒有這句會報錯,預設的ascci無法解析cp936編碼
# cp936編碼儲存
str = 'abc中文'
print str#cmd中正確顯示,因為cmd是cp936編碼
ustr = u'abc中文'#報錯,因為無法用utf-8的格式去對cp936進行解碼,
ustr1 = unicode(str, 'cp936')#正確, 因為解碼用的編碼與檔案儲存的編碼相同
=============================================
# utf-8編碼儲存
str = 'abc中文'
print str#cmd #不會報錯但是顯示為亂碼,如果放到cygwin中執行顯示正確,因為cygwin的bash是utf-8的
ustr = u'abc中文'#正確,因為python對utf-8編碼的檔案預設使用utf-8編碼集
print ustr#正常顯示,因為unicode是"通用“的編碼集,可以被轉化成其他的編碼方式
==============================================
# unicode編碼儲存,實際為utf-16le
str = 'abc'#報錯,因為utf-16的編碼會在開頭加入 FFFE兩個位元組,這個時候python會預設使用ascci來處理,因為就算你加了# -*- coding:utf-16 -*- 也沒用,因為python還沒解析到這句就已經解析失敗了