[問題] 如何用Windows版的Python在cmd中印出檔案內的Unicode字元

看板Python作者 (奔跑的蝸牛)時間13年前 (2011/04/22 20:38), 編輯推噓0(008)
留言8則, 1人參與, 最新討論串1/1
我的 XP 灌了兩個Python 1. 從官網(www.python.org)下載的2.6.6版 執行檔路徑為C:\Python26\python.exe 2. 用Cygwin的套件管理器下載的2.6.5版 執行檔路徑為C:\cygwin\bin\python.exe 假設有個文字檔C:\saki 檔案編碼為utf8 檔案內容為"咲"(不含引號) "咲"(saki)是所謂的日文漢字 並不包含在Big5字元集中 下面這個Python程式(C:\a.py)的目的是秀出stdout的編碼 然後把C:\saki的內容印出來 #coding=utf8 import sys tenc = sys.stdout.encoding print tenc s1 = open(ur'C:/saki', 'r').read().decode('utf8').encode('utf8') print s1 s2 = open(ur'C:/saki', 'r').read().decode('utf8').encode('big5') print s2 現在 在相同的環境下(皆為cmd.exe) 用兩個不同的Python執行a.py 看結果如何 <實驗1> C:>chcp 使用中字碼頁: 950 C:\>C:\Python26\python.exe a.py cp950 ?? Traceback (most recent call last): File "a.py", line 7, in <module> s2 = open(ur'saki', 'r').read().decode('utf8').encode('big5') UnicodeEncodeError: 'big5' codec can't encode character u'\u54b2' in position 0: illegal multibyte sequence <實驗2> C:>chcp 使用中字碼頁: 950 C:\>C:\cygwin\bin\python.exe a.py None Traceback (most recent call last): File "a.py", line 7, in <module> s2 = open(ur'saki', 'r').read().decode('utf8').encode('big5') UnicodeEncodeError: 'big5' codec can't encode character u'\u54b2' in position 0: illegal multibyte sequence 結果顯示 官網的Python印出無法在cmd中印出Unicode字元, 取而代之的是問號"??" Cygwin的Python印出可以正確印出Unicode字元"咲" 然後我是故意產生UnicodeEncodeError這個例外的 目的只是證明"咲"不在Big5 Charset裏 看了這樣的執行結果 產生了幾個疑問: Q1. 為什麼用官網的Python在cmd中印不出Unicode字元 用Cygwin Python卻可以呢? Q2. 為什麼同樣是在 cmd.exe 執行 a.py 兩個stdout encoding(上面標綠色的部分)卻不一樣呢? (一個是cp950 一個是None) Q3. 為什麼實驗2的stdout是None 而不是UTF-8呢? 我的 ~/.bashrc 明明有 export LANG='zh-TW.UTF-8' 了呀? Q4. 實驗2中 在chcp為950(即微軟修改的Big5)的情況下 為什麼Cygwin版的Python還是可以正確印出"咲"呢? 以下是我的猜測: A1. Python可能是把環境的locale當作自己執行時的locale 自己執行時的locale會影響執行時的Character Encoding 在Cygwin(Linux)環境下 使用者指定locale時可同時指定Character Encoding 例如我在~/.bashrc中寫 export LANG=zh_TW.UTF-8 表示locale為中文-台灣 Character Encoding為UTF-8 Cygwin Python讀取LANG的值當作執行Python時用的locale及Character Encoding 於是可以正確印出UTF-8字元 然後是Windows 繁體中文版本的Windows預設locale是zh_TW (可以透過 控制台>地區及語言選項>地區選項>標準及格式 來修改) 與Linux不同的是 在Windows中一旦locale被指定 Code Page(Character Encoding)似乎就定死了(這是我猜的 因為查不到改法) 就是cp950(cp = code page) Windows Python讀取Windows的locale的值當作執行Python時用的locale及Charset 於是就印不出UTF-8字元了 若我以上的猜測是對的 想用Windows Python在cmd.exe印出Unicode字元 就必須先讓Python使用的Code Page是UTF-8才行 在Linux下export LANG=zh_TW.UTF-8就行了 但...Windows下要怎麼做呢?? 或者 有沒有辦法直接修改Windows Python的source 來強制指定 locale-charset 為 zh_TW.UTF-8 呢? A2. Python可能是把環境的locale當作自己執行時的locale 自己執行時的locale會影響執行時的Character Encoding 所以會影響 sys.stdout.encoding A3. 不清楚 可能性太多了 總之大概是這種情況下不會 source ~/.bashrc 所以LANG是空的 所以sys.stdout.encoding也是空的 (我覺得這個問題網路上一定有人問過 還在survey中...) A4. 不清楚(這我超想知道的 拜託會的人教一下 orz) 不知道我講的對不對 有錯還請多多指教 我真的很想知道正確答案... -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.35.212.106 ※ 編輯: Holocaust123 來自: 114.35.212.106 (04/22 20:43)

04/23 02:00, , 1F
stdout encoding是cp950 python就會把他轉換過再輸出
04/23 02:00, 1F

04/23 02:00, , 2F
轉不過去就噴錯 None就不轉直接output所以就不會噴錯
04/23 02:00, 2F

04/23 02:01, , 3F
然後也要看程式跟windows tty之間用哪套api在溝通
04/23 02:01, 3F

04/23 02:01, , 4F
windows的api總是分兩套 一套吃unicode一套吃ANSI
04/23 02:01, 4F

04/23 02:02, , 5F
所謂ANSI就是locale based codepage
04/23 02:02, 5F

04/23 02:03, , 6F
吃unicode的那一套就是w開頭的東西
04/23 02:03, 6F

04/23 02:05, , 7F
亦即wchar_t 印象中cygwin的library是有正確使用unicode
04/23 02:05, 7F

04/23 02:05, , 8F
至少cwrsync用起來是這樣..
04/23 02:05, 8F
文章代碼(AID): #1DiNRYzL (Python)