以下內容說的都是 python 2.x 版本我們看到的輸入輸出都是『字元』(characters),計算機(程式)並不能直接處理,需要轉化成位元組資料(bytes),因為程式只能處理 bytes 資料。
例如:檔案、網路傳輸等,處理的都是 bytes 資料——二進位制數字。
孤立的 byte 是毫無意義的,所以我們來賦予他們含義。就引入『字符集』的概念,『字符集』就是乙個碼位(code point)對應的乙個字元的表。
該錶用於賦予 byte 意義。還需要知道乙個點:因為 ascii 字符集支援的字元太少,不能表示各個國家語言中的字元。所以就發明了
unicode ——萬國碼,該字符集包含了你能用到的所有的字元。
在 python 中字串分為兩個物件:str
和unicode
unicode_obj.encode() ——> bytes 『編碼』(encode)
bytes_obj.decode() ——> unicode 『解碼』(decode)
utf-8 是最流行的一種對 unicode 進行傳播和儲存的編碼方式。所以,多用它作為編碼方式。
s =
'hello'
# str
u =u'你好'
# unicode
back_to_bytes = u.encode('utf-8')
back_to_utf8 = back_to_bytes.decode('utf-8') # 或 unicode(s, 'utf-8')
正如前面所說的,計算機只能操作 bytes,所以 python 在編譯原檔案的時候,會先把原始檔進行編碼,預設以『ascii』進行編碼。這就是為什麼如果原始檔中帶有『中文』,需要在原始檔的起始行宣告編碼方式。
完成編碼後,原始碼中的所有字元,都變成了 bytes 計算機就可以進行編譯和處理了。編譯過程:
讀取檔案
不同的檔案,根據其宣告的編碼去解析為unicode
轉換為utf-8字串
針對utf-8字串,去分詞
編譯,建立unicode物件(python直譯器處理)
根據這個過程,在自己的**中也應該按照這個邏輯處理,意思是:
接收外部資料時,統一轉化為unicode
**內部處理的都是unicode
輸出時統一轉化為utf-8(網路資料傳輸、文字輸出)
參考:pep 263 -- defining python source code encodings
程式中所有的輸入和輸出均為 byte
世界上的文字需要比 256 更多的符號來表現(ascii是不夠的)
你的程式必須能夠處理 byte 和 unicode
byte 流中不會包含編碼資訊(編碼資訊會在:檔案的開頭、協議中等地方宣告)
content-type:text/html; charset=utf-8
指明的編碼有可能是錯誤的(出現亂碼)
在 python 中處理編碼問題,會出現很多問題,這裡就不一一枚舉。
這些問題大都是使用了不匹配的編碼方式進行解碼、編碼造成的。而 python 為了語法更加簡介,在一些內建方法中,使用了一些隱性轉換。這種**的轉換帶了的便捷的同時也會帶來一些非預期的錯誤。下面就一一道來。
a = "abc" + u"bcd"
,python 會如此轉換 "abc".decode(sys.getdefaultencoding()) 然後將兩個 unicode 字元合併。
str:something.encode(sys.getdefaultencoding())
unicode:something.decode(sys.getdefaultencoding())
sys.getdefaultencoding()
預設為:ascii,這就是為什麼str(u'中文')
和unicode('中文')
分別會報錯:unicodeencodeerror和unicodedecodeerror。因為ascii編碼方式,編碼/解碼不了中文(支援的字元有限)。
print
函式,會對輸出的內容進行編碼,這是因為:所謂的輸出,也是從乙個程式到另外乙個程式。程式之間的互動都是都是傳遞 bytes。比方說print
,就是把資料傳遞給終端,終端也是個程式,所以print
函式就把需要輸出的內容編碼成了 bytes,採用那種編碼方式,就是
由sys.stdout.encoding
引數決定的。
在互動環境下(python、ipython)輸入的資料的編碼則由sys.stdin.encoding
引數決定。參考:what does python print() function actually do?
python 的預設編髮方式為 ascii。
如何改變python的預設編碼方式?:
import sys
# sys.setdefaultencoding() does not exist, here!
reload(sys) # reload does the trick!
sys.setdefaultencoding('utf8')
為什麼要過載sys
模組?
因為如果在編譯.py
檔案的之前,改變預設編碼,會影響python的編譯。
當編譯完,再過載sys
模組,它就是變成了第三方模組,可以隨便更改,不回影響編譯。setdefaultencoding()
函式才可以呼叫。參考:changing default encoding of python?
本片文章沒有列舉出常見的異常,因為如果看懂了上面所有的解釋。再按照下面的姿勢使用,那麼 python2 中的編碼問題,因該就不會再困擾你了。
unicode 三明治:盡可能的讓你程式處理的文字都為 unicode 。如下圖:
了解你的字串。你應該知道你的程式中,哪些是 unicode, 哪些是 byte,對於這些 byte 串。你應該知道,他們的編碼是什麼。(詳情見上述小結第 4 條)
測試 unicode 支援。使用一些奇怪的符號來測試你是否已經做到了以上幾點。(測試看看你的程式是否支援中文)
Python2編碼問題
以下內容說的都是 python 2.x 版本 我們看到的輸入輸出都是 字元 characters 計算機 程式 並不能直接處理,需要轉化成位元組資料 bytes 因為程式只能處理 bytes 資料。例如 檔案 網路傳輸等,處理的都是 bytes 資料 二進位制數字。孤立的 byte 是毫無意義的,所...
python2 編碼問題
coding utf 8 import sys reload sys sys.setdefaultencoding utf8 第一行是讓 以utf8格式解析 後面三行是讓python直譯器在decode時候用utf8進行decode 這樣所有字串都是utf8的了,如果遇到非utf8字串可以用deco...
Python2 的編碼問題
比如這樣乙個字串 u6768 u777f 無論怎麼print它都是這個形式因為它是文字,不是編碼,那麼怎麼轉為中文呢,則需要用如下命令 print text.decode unicode escape 就代表著乙個字 對於這些字元,只需要使用如下命令即可從文字轉為編碼字串 print text.de...