python 處理中文遇到的編碼問題總結 以及 字符str的編碼如何判斷


如何處理中午編碼的問題

 

Python的UnicodeDecodeError: 'utf8' codec can't decode byte 0xxx in position

這個錯誤是因為你代碼中的某個字符串使用了費ascii編碼的字符,也就是它代表的16進制的編碼超過127。

解決這個問題可以使用下面的方法解決,其實就是設置默認的編碼。python 2.x的默認編碼是ascii,如果改為utf-8,就可以了。

 

import sys reload( sys )

sys.setdefaultencoding('utf-8')

 

其實從python 3.0以后默認就用utf-8,就沒有這個問題了。

 

 

新手寫pyhton程序經常遇到編碼問題,其實是對py的編碼不熟悉,經常范小毛病,郁悶好久。。。

今天終於搞懂的py的編碼。

1. pyhton的所有內置庫、方法接受的是unicode編碼的字符串。

2. str.decode 函數就是轉成unicode編碼,所以能decode的字符串傳級python的內置庫、函數都能正確運行。

3.問題在於這個decode函數解碼時到底要傳哪個參數:utf-8,gbk,gb2312......等N種編碼。參數不當,就會拋類似異常:

UnicodeDecodeError: 'gbk' codec can't decode bytes in position 2-3: illegal multibyte sequence

   UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-1: invalid data

下面舉個例子:

#coding:utf-8    

  1. #指定本文件編碼為utf8  
  2. import os  
  3. # 以下為示例代碼,不一定能運行。隨意寫的,無編譯運行過。  
  4. # 例子以XP平台為例,因為linux平台編碼(UTF-8)與window平台(GBK)不一樣。  
  5. # 假設D盤下面有很多中文名稱文件  
  6. filelist = os.listdir(r"d:\\") # 此處返回的list中的中文是以GBK編碼的,你可以通過查看cmd窗口屬性看到。  
  7. for path in filelist:  
  8.     if os.path.isdir(path): continue  
  9.      fp = open(path.decode("GBK") , 'rb')  # 如果此處用 path.decode("UTF-8") 就會拋異常,原因是wind的dir命令返回的是GBK編碼  
  10.     print len(fp.read())  
  11.      fp.close()  
  12. filepath =r"d:\\中文文件.doc"             # 假設此文存在,記得要帶中文  
  13. fp = open(filepath.decode('utf-8'), "rb") #這里使用utf8參數進行解碼,原因是文件頭里有句coding: utf-8  
  14. print len(fp.read())  
  15. fp.close()  
  16. path2 = u"d:\\中文文件.doc"  # 假如這里有個u在前面,這個變量就是unicode編碼了,不用解碼。  
  17. fp = open(path2, 'rb')  
  18. print len(fp.read())  
  19. fp.close()  
 
 
為什么Python使用過程中會出現各式各樣的亂碼問題,明明是中文字符卻顯示成“\xe4\xb8\xad\xe6\x96\x87”的形式?
 
 

為什么會報錯“UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)”?本文就來研究一下這個問題。


字符串在Python內部的表示是 unicode編碼,因此,在做編碼轉換時,通常需要以unicode作為中間編碼,即先將其他編碼的字符串解碼(decode)成unicode,再從unicode編碼(encode)成另一種編碼。

decode的作用是將其他編碼的字符串轉換成unicode編碼,如str1.decode('gb2312'),表示將gb2312編碼的字符串str1轉換成unicode編碼。

encode的作用是將unicode編碼轉換成其他編碼的字符串,如str2.encode('gb2312'),表示將unicode編碼的字符串str2轉換成gb2312編碼。

因此,轉碼的時候一定要先搞明白,字符串str是什么編碼,然后decode成unicode,然后再encode成其他編碼


代碼中字符串的默認編碼與代碼文件本身的編碼一致。

如:s='中文'

如果是在utf8的文件中,該字符串就是utf8編碼,如果是在gb2312的文件中,則其編碼為gb2312。這種情況下,要進行編碼轉換,都需要先用decode方法將其轉換成unicode編碼,再使用encode方法將其轉換成其他編碼。通常,在沒有指定特定的編碼方式時,都是使用的系統默認編碼創建的代碼文件。

如果字符串是這樣定義:s=u'中文'

則該字符串的編碼就被指定為unicode了,即python的內部編碼,而與代碼文件本身的編碼無關。因此,對於這種情況做編碼轉換,只需要直接使用encode方法將其轉換成指定編碼即可。


如果一個字符串已經是unicode了,再進行解碼則將出錯,因此通常要對其編碼方式是否為unicode進行判斷:

isinstance(s, unicode) #用來判斷是否為unicode

用非unicode編碼形式的str來encode會報錯


如何獲得系統的默認編碼?

#!/usr/bin/env python
#coding=utf-8
import sys
print sys.getdefaultencoding()

該段程序在英文WindowsXP上輸出為:ascii


在某些IDE中,字符串的輸出總是出現亂碼,甚至錯誤,其實是由於IDE的結果輸出控制台自身不能顯示字符串的編碼,而不是程序本身的問題。

如在UliPad中運行如下代碼:

s=u"中文"
print s

會提示:UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)。這是因為UliPad在英文WindowsXP上的控制台信息輸出窗口是按照ascii編碼輸出的(英文系統的默認編碼是ascii),而上面代碼中的字符串是Unicode編碼的,所以輸出時產生了錯誤。

將最后一句改為:print s.encode('gb2312')

則能正確輸出“中文”兩個字。

若最后一句改為:print s.encode('utf8')

則輸出:\xe4\xb8\xad\xe6\x96\x87,這是控制台信息輸出窗口按照ascii編碼輸出utf8編碼的字符串的結果。


unicode(str,'gb2312')與str.decode('gb2312')是一樣的,都是將gb2312編碼的str轉為unicode編碼

使用str.__class__可以查看str的編碼形式


原理說了半天,最后來個包治百病的吧:)

 

 


#!/usr/bin/env python 
#coding=utf-8 
s="中文" 

if isinstance(s, unicode): 
#s=u"中文" 
print s.encode('gb2312') 
else: 
#s="中文" 
print s.decode('utf-8').encode('gb2312')

 

 

如何判斷字符str的編碼是什么?

 

 

使用 chardet 可以很方便的實現字符串/文件的編碼檢測。尤其是中文網頁,有的頁面使用GBK/GB2312,有的使用UTF8,如果你需要去爬一些頁面,知道網頁編碼很重要的,雖然HTML頁面有charset標簽,但是有些時候是不對的。那么chardet就能幫我們大忙了。

chardet實例

>>> import urllib >>> rawdata = urllib.urlopen('http://www.google.cn/').read() >>> import chardet >>> chardet.detect(rawdata) {'confidence': 0.98999999999999999, 'encoding': 'GB2312'} >>>

chardet可以直接用detect函數來檢測所給字符的編碼。函數返回值為字典,有2個元數,一個是檢測的可信度,另外一個就是檢測到的編碼。

chardet 安裝

下載chardet后,解壓chardet壓縮包,直接將chardet文件夾放在應用程序目錄下,就可以使用import chardet開始使用chardet了。

或者使用setup.py安裝文件,將chardet拷貝到Python系統目錄下,這樣你所有的python程序只要用import chardet就可以了。

python setup.py install

 

 

 

 

總結 :

盡量把所有的input 都decode成unicode。即 str.decode('utf-8');

輸出時,再encode成所需的編碼格式

 

 

decode的作用是將其他編碼的字符串轉換成unicode編碼,如str1.decode('gb2312'),表示將gb2312編碼的字符串str1轉換成unicode編碼。

encode的作用是將unicode編碼轉換成其他編碼的字符串,如str2.encode('gb2312'),表示將unicode編碼的字符串str2轉換成gb2312編碼。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM