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

如何處理中午編碼的問題python

 

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

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

解決這個問題可使用下面的方法解決,其實就是設置默認的編碼。python 2.x的默認編碼是ascii,若是改成utf-8,就能夠了。函數

 

import sys reload( sys ) google

sys.setdefaultencoding('utf-8')編碼

 

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

 

 

新手寫pyhton程序常常遇到編碼問題,實際上是對py的編碼不熟悉,常常範小毛病,鬱悶很久。。。spa

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

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

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編碼。

相關文章
相關標籤/搜索