robot
最新文章(10)
Mqskit 和其它相關工具
CPython 的 GC 二、三事
寫 Mecurial Extension 是件快樂的事!
Mozilla 台灣辨公室徵人啟事
關於 Apple 的兩項專利
core dump 之前的 frame
怎麼發出 beep 聲?
先承認你要找的是奴才吧!
程式碼要清的多乾淨?
FreeBSD 的 Thread-Local Storage 實作
首頁
新編
最新留言
Entries RSS
重要關鍵字(10)
coding (122)
Python (93)
FreeBSD (71)
WEB (61)
URL (48)
hardware (46)
javascript (36)
Linux (34)
blog (30)
C++ (16)
所有關鍵字
新增 URL
Python 與中文
by thinker
2 Columns
關鍵字:
Python
coding
中文的支援,一直是各種程式言語的 FAQ , $Python$ 也不避免。一般來說,只要能正確的使用 'xxx'.encode('big5') 和 'xxx'.decode('big5') , Big5 中文或者其它 charset 都能正確的輸出輸入。然而,到處加入 *.encode() 和 *.decode() 實在又麻煩又醜的方案。況且,在支援多種不同解碼的情況下,也增加程式碼的複雜。 於是我嘗試使用 locale.setlocale() 來設定,發覺並不是在每個狀況都適用。當使用 print 指令時, locale 能發揮作用。但,在 $Python$-2.4.x ,如果您試著把一個 unicode 字串,透過 file.write() 輸出時,你會發覺 locale 並不能發揮作用。這是因為, $Python$ 目前並無自動偵測 locale 的設定,以改變 default encoding 。其實, site.py 已能偵測 encoding ,但這部分的 code 還在實驗階段,預設並不執行。您可以自己把這段 code enable: {{{ """Set the string encoding used by the Unicode implementation. The default is 'ascii', but if you're willing to experiment, you can change this.""" encoding = "ascii" # Default value set by _PyUnicode_Init() if 0: # Enable to support locale aware default string encodings. import locale loc = locale.getdefaultlocale() if loc[1]: encoding = loc[1] }}} 當然,上面方法有點暴力。另一個比較溫和的解法是,透過 codecs.EncodedFile() 。這個 codecs.EncodedFile() 能自動在兩個不同編碼之間轉換,例如你在記憶體內是使用 utf8 的編碼,而檔案卻是使用 big5 時,就可以透過 codecs.EncodedFile() 產生一個 file wrapper ,以進行轉碼。利用這個特性,我們可以預設使用 utf8 ,作為系統內部的 charset ,而外部的輸入則透過 codecs.EncodedFile() 做輸出入的轉碼。因此,我們只需在開檔時,或者程式一開始時,針對 stdin 、 stdout 做 wrap 即可,其餘一律以 utf8 作為 charset 。 {{{ import sys from codecs import EncodedFile file_encoding = 'big5' internal_encoding = 'utf8' sys.stdout = EncodedFile(sys.stdout, internal_encoding, file_encoding) }}} == locale == 前面提到 print 能正確的處理 locale ,能透過 locale.getlocale() 判斷 charset 。 print 其實是依據 sys.stdout.encoding 決定解碼的方式 [1],而 sys.stdout.encoding 又透過 locale 。因此,我們也可以透過 sys.stdout.encoding 取得 locale 的設定,或者從 locale.getlocale() 讀取。下面展示了這兩種方式: {{{ import sys, locale print sys.stdout.encoding locale.setlocale(locale.LC_CTYPE, '') lc_ctype = locale.getlocale(locale.LC_CTYPE) print lc_ctype[1] }}} 使用 locale ,透過設定環境變數 LC_ALL 或 LC_CTYPE ,就能在不同 charset 之間切換。我個人的建議是,內部 charset 使用 utf8 ,在 unicode 輸出時,全都以 utf8 編碼。例如,從 $database$ 讀取的 unicode 字串,也先使用 *.encode('utf8') 編碼成 utf8 。然後再透過 wrapper 轉成外部的 charset ,並且輸出。如: {{{ from codecs import EncodedFile import sys internal_encoding = 'utf8' file_encoding = sys.stdout.encoding stdout = EncodedFile(sys.stdout, internal_encoding, file_encoding) # fetch data from $database$ row = cu.fetchone() _str = row[0].encode('utf8') stdout.write(_str) }}} 注意! 前面提到 print 能正確的處理 locale 。因此,只有針對 file.read() 和 file.write() 才需要特別處理。 == References == # linkname:[A Crash Course in Character Encoding] http://www.pyzine.com/Issue008/Section_Articles/article_Encodings.html # linkname:[codecs -- Codec registry and base classes] http://docs.python.org/lib/module-codecs.html
最後更新時間: 2007-01-01 23:59:26 CST |
引用
查詢:
COMMENTS: