python對多國語言的處理是支持的很好的,它可以處理現在任意編碼的字符,這里深入的研究一下python對多種不同語言的處理。
有一點需要清楚的是,當python要做編碼轉換的時候,會借助於內部的編碼,轉換過程是這樣的:
原有編碼 -> 內部編碼 -> 目的編碼
python的內部是使用unicode來處理的,但是unicode的使用需要考慮的是它的編碼格式有兩種,一是UCS-2,它一共有65536個碼 位,另一種是UCS-4,它有2147483648g個碼位。對於這兩種格式,python都是支持的,這個是在編譯時通過--enable- unicode=ucs2或--enable-unicode=ucs4來指定的。那么我們自己默認安裝的python有的什么編碼怎么來確定呢?有一個 辦法,就是通過sys.maxunicode的值來判斷:
import sys
print sys.maxunicode
如果輸出的值為65535,那么就是UCS-2,如果輸出是1114111就是UCS-4編碼。
我們要認識到一點:當一個字符串轉換為內部編碼后,它就不是str類型了!它是unicode類型:
a = " 風卷殘雲 "
print type(a)
b = unicode(a, " gb2312 " )
print type(b)
輸出:
<type 'str'>
<type 'unicode'>
這個時候b可以方便的任意轉換為其他編碼,比如轉換為utf-8:
c = b.encode( " utf-8 " )
print c
c輸出的東西看起來是亂碼,那就對了,因為是utf-8的字符串。
好了,該說說codecs模塊了,它和我上面說的概念是密切相關的。codecs專門用作編碼轉換,當然,其實通過它的接口是可以擴展到其他關於代碼方面的轉換的,這個東西這里不涉及。
codecs模塊中重要的函數之一是lookup,它只有一個參數encoding,指的是編碼方式的名稱,即utf-8或者gb2312等等。
lookup函數返回一個包含四個元素的TUPLE,其中t[0]是encoder的函數引用,t[1]是decoder的函數引用,t[2] 是UTF-8編碼方式的StreamReader類對象引用,t[3]是UTF-8編碼方式的StreamWriter類對象引用相信對Python熟悉的你肯定知道接下來該怎么用它們了。
codecs模塊還提供了方便程序員使用的單獨函數,以簡化對lookup的調用。它們是:
- getencoder(encoding)
- getdecoder(encoding)
- getreader(encoding)
- getwriter(encoding)
如果我們只是想獲取一種utf-8編碼的encoder方法,那么只需要這樣做:
>>> encoder = codecs.getencoder("utf-8")
上面的代碼就是codecs的使用,是最常見的用法。另外還有一個問題就是,如果我們處理的文件里的字符編碼是其他類型的呢?這個讀取進行做處理也需要特殊的處理的。codecs也提供了方法.
python讀寫文件估計大家都用open內置函數,或者file這個工廠函數,這兩個的效果基本一樣。
打開文件的方式一般為:f=open(file_name,access_mode = 'r',buffering = -1)。file_name就是文件的路徑加文件名字,不加路徑則文件會存放在python程序的路徑下,
access_mode就是操作文件的模式,主要有r,w,rb,wb等,細節網上一大堆,buffering = -1是用於指示訪問文件所采用的緩存方式。0表示不緩存;1表示只緩存一行,n代表緩存n行。如果不提供或為負數,則代表使用系統默認的緩存機制。
打開以后就是寫和讀的操作。但是用open方法打開會有一些問題。open打開文件只能寫入str類型,不管字符串是什么編碼方式。例如
>>> fr = open('test.txt','a')
>>> line1 = "我愛祖國"
>>> fr.write(line1)
這樣是完全可以的。但是有時候我們爬蟲或者其他方式得到一些數據寫入文件時會有編碼不統一的問題,所以就一般都統一轉換為unicode。此時寫入open方式打開的文件就有問題了。例如
>>> line2 = u'我愛祖國'
>>> fr.write(line2)
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
fr.write(line2)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-11: ordinal not in range(128)
>>>
怎么辦,我們可以將上面的line2編碼成str類型,但是太麻煩。我們要把得到的東西先decode為unicode再encode為str。。。
input文件(gbk, utf-8...) ----decode-----> unicode -------encode------> output文件(gbk, utf-8...)
代替這繁瑣的操作就是codecs.open,例如
>>> import codecs
>>> fw = codecs.open('test1.txt','a','utf-8')
>>> fw.write(line2)
>>>
不會報錯,說明寫入成功。這種方法可以指定一個編碼打開文件,使用這個方法打開的文件讀取返回的將是unicode。寫入時,如果參數 是unicode,則使用open()時指定的編碼進行編碼后寫入;如果是str,則先根據源代碼文件聲明的字符編碼,解碼成unicode后再進行前述 操作。相對內置的open()來說,這個方法比較不容易在編碼上出現問題。
# -*- encoding: gb2312 -*-
import codecs, sys
# 用codecs提供的open方法來指定打開的文件的語言編碼,它會在讀取的時候自動轉換為內部unicode
bfile = codecs.open( " dddd.txt " , ' r ' , " big5 " )
# bfile = open("dddd.txt", 'r')
ss = bfile.read()
bfile.close()
# 輸出,這個時候看到的就是轉換后的結果。如果使用語言內建的open函數來打開文件,這里看到的必定是亂碼
print ss, type(ss)
總結一下,codecs模塊為我們解決的字符編碼的處理提供了lookup方法,它接受一個字符編碼名稱的參數,並返回指定字符編碼對應的 encoder、decoder、StreamReader和StreamWriter的函數對象和類對象的引用。為了簡化對lookup方法的調用, codecs還提供了getencoder(encoding)、getdecoder(encoding)、getreader(encoding)和 getwriter(encoding)方法;進一步,簡化對特定字符編碼的StreamReader、StreamWriter和 StreamReaderWriter的訪問,codecs更直接地提供了open方法,通過encoding參數傳遞字符編碼名稱,即可獲得對 encoder和decoder的雙向服務。