作者Holocaust123 (奔跑的蜗牛)
看板Python
标题[问题] 如何用Windows版的Python在cmd中印出档案内的Unicode字元
时间Fri Apr 22 20:38:56 2011
我的 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)
1F:→ buganini:stdout encoding是cp950 python就会把他转换过再输出 04/23 02:00
2F:→ buganini:转不过去就喷错 None就不转直接output所以就不会喷错 04/23 02:00
3F:→ buganini:然後也要看程式跟windows tty之间用哪套api在沟通 04/23 02:01
4F:→ buganini:windows的api总是分两套 一套吃unicode一套吃ANSI 04/23 02:01
5F:→ buganini:所谓ANSI就是locale based codepage 04/23 02:02
6F:→ buganini:吃unicode的那一套就是w开头的东西 04/23 02:03
7F:→ buganini:亦即wchar_t 印象中cygwin的library是有正确使用unicode 04/23 02:05
8F:→ buganini:至少cwrsync用起来是这样.. 04/23 02:05