python編碼問題

2021-08-16 16:05:45 字數 4258 閱讀 9537

編碼問題,一直是使用python2時的一塊心病。幾乎所有的控制台輸入輸出、io操作和http操作都會涉及如下的編碼問題:

unicodedecodeerror:『

ascii

』codec can

』t decode

byte

0xc4

inposition 10:

ordinal

notin

range

(128

)

這究竟是是個什麼東西?!有時稀里糊塗地用一坨encode(),decode()之類的函式讓程式能跑對了,可是下次遇到非ascii編碼時又悲劇了。

那麼python 2.x中的字串究竟是個什麼呢?

在了解python中字串(string)的本質前,我們需要知道ascii、gbk、utf-8和unicode的關係究竟幾何。

我們知道,任何字串都是一串二進位制位元組的序列,而ascii碼是最經典的編碼方式,它將序列中的每個位元組理解為乙個字元,可表示阿拉伯數字、字母在內的128個不同字元。很明顯,漢字在ascii中是無法表示的。

為了讓計算機能夠顯示、處理漢字,勤勞樸實的中國人民制定了gbk(gb2312的擴充套件)編碼,這是一種相容ascii的不定長(長度為1-2)編碼,對於基本的128個字元仍舊用乙個位元組表示,但「翔」這樣的中文就用兩個位元組表示:

utf-8與gbk類似,也是一種相容ascii碼的不定長編碼形式,它的長度變化更大,因此可以表示幾乎所有世界文字。具體細節可參考維基:

unicode是一種定長的編碼方式(同ascii),不過它是每2位元組認為是乙個字元,如ascii中0x61表示'a',在unicode中用0x0061表示'a',它可對映所有文字,而且對於多種寫法的字,如強/強,它都可以唯一地區分它們。

由於unicode編碼的字串體積很大,因此一般來說unicode編碼只是文字在記憶體中的內在形式,具體的儲存(如檔案、網頁等)都需要靠外在的編碼(utf-8、gbk等)詮釋。

python中實際上有兩種字串,分別是str型別和unicode型別,這兩者都是basestring的派生類。它們的區別如下:

字串型別

常量子串表示

記憶體中表示

len()

len含義

strs=「呵呵」

與原始碼檔案完全一致,一坨二進位制編碼

若原始碼檔案為utf-8編碼,

len(s)=6

位元組數unicode

s=u「呵呵」

unicode編碼

len(s)=2

字數str型別的本質就是一坨二進位制串,原始檔(或獲取的網頁)的編碼是怎樣,它就跟著是怎樣。實際上python並不清楚某個str字串到底是什麼編碼。這也就解釋了為什麼我們需要在python檔案的開頭標定該檔案的編碼是什麼,如:

# encoding: utf-8
也解釋了為什麼len()乙個str型別的字串,只會返回它在記憶體中占用的位元組數,而非文字數。

相比於str,unicode是真正的字串。python明確地知道它的編碼,所以可以很自信地獲得乙個字串的實際字數。

python最常用的編碼轉換函式是encode()和decode(),他們的本質是:unicode和str的互相轉換。

具體而言:

encode(encoding): 將unicode轉換為str,並使用encoding編碼;

decode(encoding):將str轉換為unicode,其中str以encoding編碼。

我們來看乙個例子:

#encoding: utf-8s =

"你好"

# 整個檔案是utf-8編碼,所以這裡的字串也是utf-8u =

s.decode

("utf-8"

)# 將utf-8的str轉換為unicodeg =

u.encode

('gbk'

)# 將unicode轉換為str,編碼為gbk

print

type(s

),"len="

,len(s

)# 輸出: len= 6,utf-8每個漢字佔3位元組

print

type(u

),"len="

,len(u

)# 輸出: len= 6,unicode統計的是字數

print

type(g

),"len="

,len(g

)# 輸出:g = u.encode('gbk'),gbk每個漢字佔2位元組

print

s # 在gbk/ansi環境下(如windows),輸出亂碼,

#因為此時螢幕輸出會被強制理解為gbk;linux下顯示正常

print

g # 在windows下輸出「你好」,

#linux(utf-8環境)下報錯,原因同上。

在windows7(中文)下執行結果如下:

len=6

len=

2len=4

浣犲ソ你好

traceback

(most recent call

last

):file

"c:/users/sunicy/desktop/encode.py"

,line 15,

ing.decode

('utf-8'

)file

"c:\python27\lib\encodings\utf_8.py"

,line 16,

indecode

return

codecs

.utf_8_decode

(input

,errors

,true

)unicodedecodeerror

:'utf8'

codec can

't decode byte 0xc4 in position 0: invalid continuation byte

我們知道python中判斷乙個變數是否為某個型別使用isinstance(變數, 型別)函式,如

isinstance

(1.2

,float

)

返回值為true

那麼判斷變數是不是字串能不能用

isinstance(s

,str

)

呢?

答案是否定的。

現在我們知道除了str之外,unicode型別也是字串,因此上述**如果遇到unicode字串,就返回false。

直觀地改進是既判斷str又判斷unicode:

isinstance(s

,str)or

isinstance(s

,unicode

)

不過這個方法有效,但是有點傻。既然str和unicode都派生自basestring,那麼實際上以basestring作為型別是最穩妥的:

isinstance(s

,basestring

)

下面是一組例子:

isinstance

("aaa"

,str

)# -> true

isinstance

({},

dict

)# -> true

isinstance([1

,],list

)# -> true

isinstance

("aaa"

,list

)# -> false

isinstance

("你"

,str

)# -> false

isinstance

("你好"

,basestring

)# -> true

isinstance

("aaa"

,basestring

)# -> true

unicode是支援所有文字的統一編碼,但一般只用作文字的內部表示,檔案、網頁(也是檔案)、螢幕輸入輸出等處均需使用具體的外在編碼,如gbk、utf-8等;

encode和decode都是針對unicode進行「編碼」和「解碼」,所以encode是unicode->str的過程,decode是str->unicode的過程;

unicode和str是一對孿生兄弟,來自basestring,所以用isinstance(s, basestring)來判斷s是否為字串。

python中gbk, utf-8和unicode的編碼問題, 感謝原作者分享。

Python編碼問題

tag python,encoding,unicode 現有的字元編碼 ascii,gbk,gb2312,utf 8,unicode.unicode可以用來表示所有語言的字元,而且是定長雙位元組 也有四位元組的 編碼,包括英文本母在內。python中定義乙個unicode字串和定義乙個普通字串一樣簡...

python編碼問題

python裡面基本上要考慮三種編碼格式 1 原始檔編碼 在檔案頭部使用coding宣告。告訴python直譯器該 檔案所使用的字符集。usr bin python coding utf8 2 內部編碼 檔案中的字串,經過decode以後,被轉換為統一的unicode格式的內部資料,類似於u uni...

Python編碼問題

python裡面基本上要考慮三種編碼格式 1 原始檔編碼 在檔案頭部使用coding宣告。告訴python直譯器該 檔案所使用的字符集。usr bin python coding utf8 2 內部編碼 檔案中的字串,經過decode以後,被轉換為統一的unicode格式的內部資料,類似於u uni...