Python 的編碼


在Python 2.x,程式中所有字串,其實都是原始位元組集合。如果原始碼中寫了非 ASCII 字元串,必須在第一行放置編碼聲明(encoding declaration)。例如:

# coding=Big5
text = '測試'
print len(text) # 顯示 4

程式會顯示 4 而不是 2,因為 Big5 每個中文字佔兩個位元組,而兩個中文字就佔四個位元組,所以上例中,len() 實際上是計算出 '測試' 兩字 Big5 編碼實現下的位元組長度。

為了支援 Unicode,Python 2.x 提供了 u 前置字來產生 unicode 物件。

# coding=Big5
text = u'測試'
print type(text) # 顯示 <type 'unicode'>
print len(text)  # 顯示 2

chr() 可取一個數字傳回對應 ASCII 編碼的 str 實例,unichr() 是其 Unicode 對應版本,可傳回對應 Unicode 碼點的 unicode 實例。ord() 可接受 strunicode 實例,分別傳回其 ASCII 編碼或 Unicode 碼點。例如:

>>> chr(65)
'A'
>>> unichr(65)
u'A'
>>> unichr(28204)
u'\u6e2c'
>>> ord('A')
65
>>> ord(u'A')
65
>>> ord(u'測')
28204
>>>

如果有一個 str 實例,可以使用 unicode() 方法並指定實現編碼,或者使用 strdecode 方法並指定實現編碼,將之轉換為 unicode 物件。unicodeencode() 方法則可指定實現編碼,將之轉為代表位元組實現的 str 實例。例如:

>>> text = u'測試'
>>> b_str = text.encode('big5')
>>> type(b_str)
<type 'str'>
>>> b_str.decode('big5')
u'\u6e2c\u8a66'
>>> unicode(b_str, "big5")
u'\u6e2c\u8a66'
>>>

在讀取文字檔案時,進入的資料都以代表位元組的 str 表示,若讀取非 ASCII 的文字檔案,必須自行轉換編碼。例如若有個 UTF-8 的文字檔案 text.txt 中記錄了「測試」兩字,則程式讀取時可如下:

with open('text.txt', 'r') as f:
    b_str = f.read()
    print b_str.decode('utf-8')  # 自行判斷標準輸出編碼
    print b_str.decode('utf-8').encode('big5') # 標準輸出編碼為 big5

以上最後兩句都會在標準輸出顯示「測試」兩字。類似地,如果要將 unicode 寫入文字檔案,必須使用 encode() 轉換為指定編碼實現。例如,以下程式可將「測試」以Big5編碼寫入文字檔案:

# coding=utf-8
text = u'測試'
b_str = text.encode('big5')
with open('text.txt', 'w') as f:
    f.write(b_str)

在 Python 3.x 中,預設 .py 檔案必須是 UTF-8 編碼。如果 .py 檔案想要是 UTF-8 以外的編碼,同樣必須在第一行放置編碼聲明。

# coding=Big5
text = '測試'
print(len(text)) # 顯示 2

Python 3.x 中的字串都是 Unicode,因此上例最後是顯示 2,表示兩個字元,而不是像 Python 2.x 中,會顯示字串實際的位元組長度。

在 Python3 中,每個字串都是 Unicode,不使用內部編碼表現,而使用 str 實例作為代表。如果想將字串轉為指定的編碼實作,可以使用 encode() 方法取得一個 bytes 實例,如果有個 bytes 實例,也可以使用 decode() 方法指定編碼取得 str 實例:

>>> '元'.encode('big5')
b'\xa4\xb8'
>>> '元'.encode('utf-8')
b'\xe5\x85\x83'
>>> '元'.encode('big5').decode('big5')
'元'
>>>

如果要將資料寫入檔案或從檔案讀出,可以使用 open() 函式,其中可以指定編碼:

open(file,mode="r",buffering=None,encoding=None,
     errors=None,newline=None,closefd=True)

例如,若要讀取 UTF-8 文字檔案:

name = input('請輸入檔名:')
with open(name, 'r', encoding='UTF-8') as file:
    content = file.read()
    print(content)

讀入的結果為 str 實例。若要將 str 實例寫入 Big5 編碼文字檔案可如下:

name = input('請輸入檔名:')
with open(name, 'w', encoding = 'Big5') as file:
    file.write('test')