1. 程式人生 > >python2 中文編碼問題小結

python2 中文編碼問題小結

最近處理中文資料,python2各種編碼問題,看了好多部落格和文章,終於弄懂了一些,所以在這裡總結一發。供大家學習和參考!

1.編碼

(1)ASCII碼

ASCII碼是規定的最早的計算機系統將英文文字轉為數字儲存的編碼方式,一共規定了128個字元的編碼,即7個bit。而1byte=8bit,所以佔一個位元組的ASCII碼的最高位(沒用到)為0。

(2)Unicode

由於ASCII碼只包含了大小寫英文字母、數字和一些符號,如果用來表示其他語言,那麼是不行的。因此產生了一些非ASCII編碼方式。

簡體中文常見的編碼方式是GB2312,使用兩個位元組表示一個漢字,所以理論上最多可以表示256x256=65536個符號。

但是每個地方的編碼標準都不一樣,如何統一呢?Unicode就出現了。

Unicode叫做萬國碼,採用32位二進位制(4位元組)表示一個字元。但是需要注意的是,Unicode只是一個符號集(指定字元到二進位制數之間的對應關係),它只規定了符號的二進位制程式碼,卻沒有規定這個二進位制程式碼應該如何儲存。

(3)UTF-8

Unicode的實現方式有很多種,比如

  • UTF-8 :(變長的編碼方式,可以使用2~4個位元組表示一個符號,根據不同的符號而變化位元組長度)
  • UTF-16:(變長的編碼方式,可以使用2~4個位元組表示一個符號,根據不同的符號而變化位元組長度)
  • UTF-32:(每個字元固定佔4位元組)

而UTF-8(8-bit Unicode Transformation Format)是在網際網路上使用最廣的一種Unicode的實現方式。

2.Python 編碼

python2預設以ASCII編碼,但是在實際編碼過程中,我們會用到很多中文,為了不使包含中文的程式報錯,也是為了符合國際通用慣例,一般將我們的檔案編碼設定為utf-8格式。
如何設定:一般在檔案開頭宣告

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

Python中有兩個常用的由basestring派生出來的表示字串的型別:str, unicode。
其中,str類似於C中的字元陣列或者Java中的byte陣列。
對於unicode型別,Python在記憶體中儲存和使用的時候是按照UTF-8方式,在程式碼中的表示為字串前加u。

而unicode與str之間的轉換,則用到了encode和deocde方法。
decode解碼:表示將一個(str)字串按照給定的編碼解析為unicode型別,encode編碼:表示將一個unicode字串按照指定編碼解析為位元組陣列(str)

3.sys.setdefaultencoding(‘utf-8’) 問題

為什麼我們有時候遇到編碼問題時,還經常看到一種解決方式reload(sys),sys.setdefaultencoding(‘utf-8’) ?

若str物件呼叫encode會預設先按系統預設編碼方式 decode成unicode物件再encode,忽視了中間預設的decode往往導致報錯
比如有如下程式碼:

  # -*- coding: utf-8 -*- 
  s = '中文字元'  # 這裡的 str 是 str 型別的,而不是 unicode 
  s.encode('gb2312') 

這句程式碼將 s 重新編碼為 gb2312 的格式,即進行 unicode -> str 的轉換。因為 s 本身就是 str 型別的,因此
Python 會自動的先將 s 解碼為 unicode ,然後再編碼成 gb2312。因為解碼是python自動進行的,我們沒有指明解碼方式,python 就會使用 sys.defaultencoding 指明的方式來解碼。很多情況下 sys.defaultencoding為ANSCII,如果 s 不是這個型別就會出錯。

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 
  0: ordinal not in range(128) 

對於這種情況,我們有兩種方法來改正錯誤:
(1)明確的指示出 s 的編碼方式

 #! /usr/bin/env python 
  # -*- coding: utf-8 -*- 
  s = '中文字元' 
  s.decode('utf-8').encode('gb2312') 

(2)更改 sys.defaultencoding 為檔案的編碼方式

  # -*- coding: utf-8 -*- 
  import sys 
  reload(sys) # Python2.5 初始化後刪除了 sys.setdefaultencoding 方法,我們需要重新載入 
  sys.setdefaultencoding('utf-8') 

  str = '中文字元' 
  str.encode('gb2312')

總結:

1. 編碼問題在python2中還是挺麻煩的,尤其是處理中文,裡面的坑大概我都遇到過了。我建議一上來先加coding那句話,順帶把reload也加上吧。這樣避免之後程式報錯又重新來找問題。(我也有看到文章說reload(sys)似乎並不是很好,我覺得其實最好的辦法是我們都換python3 吧^_^)

2. 搞懂Unicode和UTF-8之間的關係(只是實現方式)。

3. 搞懂 python中編碼encode和解碼decode是在幹什麼。str到unicode為解碼,unicode到str為編碼。如果某種str到另一種str,其中會先用系統預設方式decode解碼,再encode編碼。

參考部落格:
阮一峰-字元編碼筆記:ASCII,Unicode和UTF-8
(寫的很贊啊!我的很多地方都是看了他的部落格弄懂的)
聊一聊 Python 2 中的編碼
這篇文章encode,decode寫的很清楚呀~而且也非常通俗易懂,膜拜大佬~