Python編碼問題詳解

來源:互聯網
上載者:User

標籤:

1.Python編碼基礎1.1 str和unicode

python中有兩種資料模型來支援字串這種資料類型,str和unicode,它們的基類都是basestring。比如s = "中文"就是str類型的字串,而u=u"中文"就是一個unicode類型的字串。unicode是由str類型的字串解碼後得到,unicode也可以編碼成str類型。即

 

str --> decode -->unicodeunicode --> encode --> str

 

嚴格來說,str也許應該叫做位元組串,因為對於UTF-8編碼的str類型"中文",使用len()函數得到的結果是6,因為UTF-8編碼的str類型“中文”實際是"\xe4\xb8\xad\xe6\x96\x87"。而對於unicode類型u“中文”(實際是u"\u4e2d\u6587"),使用len()函數得到結果是2.
1.2 頭部編碼聲明

在python原始碼檔案中如果有用到非ascii字元,比如中文,那麼需要在源碼檔案頭部聲明原始碼字元編碼,格式如下:

 

#-*- coding: utf-8 -*-

 

這個格式看起比較複雜,其實python只檢查#、coding,編碼等字串,可以簡寫成#coding:utf-8,甚至還可以寫成#coding:u8。

 

2.Python2.x常見編碼問題2.1 頭部編碼聲明和檔案編碼問題

檔案頭部編碼聲明決定了python解析源碼中的str的編碼選擇方式,比如頭部聲明的是utf-8編碼,則代碼中s="中文"python就會按照utf-8編碼格式來解析,通過repr(s)可以看到字元編碼是"\xe4\xb8\xad\xe6\x96\x87",如果頭部聲明的編碼是gbk編碼,則python會對s採用gbk編碼解析,結果是"\xd6\xd0\xce\xc4"

需要注意的是,檔案本身的編碼要跟檔案頭部聲明編碼一致,不然就會出現問題。檔案本身的編碼在Linux下面可以在vim下用命令set fenc來查看。如果檔案本身編碼是gbk,而源碼檔案頭部聲明的編碼是utf-8,這樣如果源碼中有中文就會有問題了,因為本身中文str儲存是按照gbk編碼來的,而python在解析str的時候又以為是utf-8編碼,這樣就會報SyntaxError: (unicode error) ‘utf8‘ codec can‘t decode byte錯誤。

2.2 預設編碼問題

下面看個python預設編碼導致的問題:

 

#coding: utf-8u = u"中文"print repr(u) # u‘\u4e2d\u6587‘s = "中文"print repr(s) # ‘\xe4\xb8\xad\xe6\x96\x87‘u2 = s.decode("utf-8")print repr(u2) # u‘\u4e2d\u6587‘#s2 = u.decode("utf-8") #編碼錯誤#u2 = s.encode("utf-8") #解碼錯誤

 

 

注意執行個體中注釋掉的2行代碼,對於unicode最好不要直接調用decode,str最好不要直接調用encode方法。因為如果是直接調用,則相當於u.encode(default_encoding).decode("utf-8"),default_encoding是python的unicode實現中用的預設編碼,即sys.getdefaultencoding()得到的編碼,如果你沒有設定過,那麼預設編碼就是ascii,如果你的unicode本身超出了ascii編碼範圍就會報錯。同理,如果對str直接調用encode方法,那麼預設會先對str進行解碼,即s.decode(default_encoding).encode("utf-8"),如果str本身是中文,而default_encoding是ascii的話,解碼就會出錯,從而導致上面這兩行會分別報UnicodeEncodeError: ‘ascii‘ codec can‘t encode characters in position...錯誤和UnicodeDecodeError: ‘ascii‘ codec can‘t decode byte 0xe4 in position...錯誤。

上面例子中注釋掉的兩行代碼如果執行就會報錯,當然,如果本身str或者unicode都在ascii編碼範圍,就沒有問題。比如s = "abc"; s.encode("utf-8")就不會有問題,語句執行後會返回一個跟s的id不同的str。

那如果要解決執行個體1中的問題,有兩種方法,其一是明確指定編碼,如下所示:

 

#coding: utf-8u = u"中文"print repr(u) # u‘\u4e2d\u6587‘s = "中文"print repr(s) # ‘\xe4\xb8\xad\xe6\x96\x87‘u2 = s.decode("utf-8")print repr(u2) # u‘\u4e2d\u6587‘s2 = u.encode("utf-8").decode("utf-8")  # OK                                    u2 = s.decode("utf8").encode("utf-8")   # OK

 

 

第二種方法就是更改python的預設編碼為檔案編碼格式,如下所示(這裡只所以要reload sys模組,是因為python初始化後刪除了setdefaultencoding方法):
#coding:utf-8                                                                   import sys reload(sys)sys.setdefaultencoding("utf-8") #更改預設編碼為utf-8u = u"中文"print repr(u) # u‘\u4e2d\u6587‘s = "中文"print repr(s) # ‘\xe4\xb8\xad\xe6\x96\x87‘u2 = s.decode("utf-8")print repr(u2) # u‘\u4e2d\u6587‘s2 = u.decode("utf-8")u2 = s.encode("utf-8")
2.3讀寫檔案編碼

採用python的open()方法開啟檔案時,read()讀取的是str,編碼就是檔案本身的編碼。而調用write()寫檔案時,如果參數是unicode,則需要用指定編碼encode,如果write()參數是unicode而且沒有指定編碼,則會採用python預設編碼encode後再寫入。

 

#coding:utf-8                                                                   f = open("testfile")s = f.read()f.close()print type(s) # u = s.decode("utf-8") #testfile是utf-8編碼f = open("testfile", "w")f.write(u.encode("gbk")) #以gbk編碼寫入,testfile為gbk編碼f.close()

 

此外,python的codecs模組提供了一個open()方法,可以指定編碼開啟檔案,使用這個方法開啟檔案讀取返回是unicode。寫入時,如果write參數是unicode,則使用開啟檔案時的編碼寫入,如果是str,則先使用預設編碼解碼成unicode後再以開啟檔案的編碼寫入(這裡需要注意如果str是中文,而預設編碼sys.getdefaultencoding()是ascii的話會報解碼錯誤)。

 

#coding:gbkimport codecsf = codecs.open(‘testfile‘, encoding=‘utf-8‘)u = f.read()f.close()print type(u) # f = codecs.open(‘testfile‘, ‘a‘, encoding=‘utf-8‘)f.write(u) #寫入unicode# 寫入gbk編碼的str,自動進行解碼編碼操作s = ‘漢‘print repr(s) # ‘\xba\xba‘# 這裡會先將GBK編碼的str解碼為unicode再編碼為UTF-8寫入#f.write(s) #預設編碼為ascii時,這會報解碼錯誤。f.close()


參考
http://www.2cto.com/kf/201407/317866.html

Python編碼問題詳解

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.