Python 中的 str 與 unicode 編碼處理

問題

用 Python 處理中文時會經常發現亂碼(字符串處理,讀寫文件,print),多數的做法是調用encode/decode進行調試,並沒有明確思考爲何出現亂碼,所以調試時常出現錯誤。

理論

若要完全掌握字符編碼的處理,必須理解基本知識如 字符編碼 | ASCII | Unicode | UTF-8 等。
另外也有一些好的文章可以參考:
字符編碼筆記:ASCII,Unicode和UTF-8
淘寶搜索技術博客–中文編碼雜談

示例

Python 中的 str 和 unicode 都是 basestring 的子類
判斷是否是字符串的方法:

def is_str(s):
    return isinstance(s, basestring)

str 和 unicode 的轉換

str -> decode('the_coding_of_str') -> unicode
unicode -> encode('the_coding_you_want') -> str

s.decode 方法和 u.encode 方法是最常用的,簡單說來就是,Python內部表示字符串用 unicode(其實python內部的表示和真實的unicode是有點差別的,對我們幾乎透明,可不考慮),和人交互的時候用str對象。
似乎有了 unicode 對象的 encode 方法和 str 的 decode 方法就足夠了。奇怪的是 unicode 也有 decode,而 str 也有 encode。
“str.encode(e) is the same as unicode(str).encode(e).
This is useful since code that expects Unicode strings should also work when it is passed ASCII-encoded 8-bit strings.”(from Guido van Rossum)
這段話大概意思是說encode方法本來是被unicode調的,但如果不小心被作爲str對象的方法調,並且這個str對象正好是ascii編碼的(ascii這一段和unicode是一樣的),也應該讓他成功。這就是str.encode方法的一個用處 。

str 是字節串,由unicode經過編碼(encode)後的字節組成。
1.聲明:

s1 = '中文'  #<type 'str'> 
s2 = u'中文' #<type 'unicode'>
s3 = s2.encode('utf-8') #<type 'str'>
s4 = s1.decode('gbk')   #<type 'unicode'>

2.求長度(返回字節數):

>>> u'中文'.encode('utf-8')
‘\xe4\xb8\xad\xe6\x96\x87‘
>>> len(u'中文'.encode('utf-8'))
6

unicode纔是真正意義上的字符串,由字符組成。
3.聲明

s1 = u'中文' #<type 'unicode'> 
s2 = '中文'.decode('gbk') #<type 'unicode'> 
s3 = unicode('中文', 'utf-8') #<type 'unicode'> 

4.求長度(返回字符數),在邏輯中真正想要用的

>>> u'中文' 
u'\u4e2d\u6587'
>>> len(u'中文')
2

5.判斷是否爲unicode/str的方法

>>> isinstance(u'中文', unicode) 
True 
>>> isinstance('中文', unicode) 
False
>>> isinstance('中文', str)
True
>>> isinstance(u'中文', str) 
False

總結

使用 Python 處理編碼時,輸入字符全部轉成 unicode, 程序內部全部使用unicode處理,輸出再轉成目標編碼(當然,有例外,處理邏輯中要用到具體編碼的情況)。
.py文件默認編碼是ASCII,在源代碼文件中,如果用到非ASCII字符,需要在文件頭部進行編碼聲明,否則,輸入非ASCII會遇到的錯誤。

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

或者

# coding='utf-8'

若頭部聲明coding=’utf-8’, a= ‘中文’ 其編碼爲utf-8
若頭部聲明coding=’gb2312’, a=’中文’ 其編碼爲gbk

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章