我有什么遗漏的吗?还是这是Python的一个bug?Windows?注:我在运行Windows 7 EN的Python 2.6.6上,语言环境设置为法语(瑞士)。
在下面的测试程序中,我检查文字是否被正确解释并可以打印 - 这个是有效的。但是我传递给命令行的所有值似乎都被错误地编码:
#!/usr/bin/python
# -*- encoding: utf-8 -*-
import sys
literal_mb = 'utf-8 literal: üèéÃÂç€ÈÚ'
literal_u = u'unicode literal: üèéÃÂç€ÈÚ'
print "Testing literals"
print literal_mb.decode('utf-8').encode(sys.stdout.encoding,'replace')
print literal_u.encode(sys.stdout.encoding,'replace')
print "Testing arguments ( stdin/out encodings:",sys.stdin.encoding,"/",sys.stdout.encoding,")"
for i in range(1,len(sys.argv)):
arg = sys.argv[i]
print "arg",i,":",arg
for ch in arg:
print " ",ch,"->",ord(ch),
if ord(ch)>=128 and sys.stdin.encoding == 'cp850':
print "<-",ch.decode('cp1252').encode(sys.stdout.encoding,'replace'),"[assuming input was actually cp1252 ]"
else:
print ""
在新创建的控制台中运行时:
C:\dev>test-encoding.py abcé€
我得到以下输出
Testing literals
utf-8 literal: üèéÃÂç?ÈÚ
unicode literal: üèéÃÂç?ÈÚ
Testing arguments ( stdin/out encodings: cp850 / cp850 )
arg 1 : abcÚÇ
a -> 97
b -> 98
c -> 99
Ú -> 233 <- é [assuming input was actually cp1252 ]
Ç -> 128 <- ? [assuming input was actually cp1252 ]
尽管我期望第四个字符的序数值为130而不是233(请参见代码页850和1252)。
注:欧元符号为128的值是一个谜 - 因为cp850没有它。否则,“?”是预期的 - cp850无法打印这些字符,我在转换中使用了“replace”。
如果我通过发出chcp 1252
将控制台的代码页更改为1252并运行相同的命令,则可以(正确地)获得
Testing literals
utf-8 literal: üèéÃÂç€ÈÚ
unicode literal: üèéÃÂç€ÈÚ
Testing arguments ( stdin/out encodings: cp1252 / cp1252 )
arg 1 : abcé€
a -> 97
b -> 98
c -> 99
é -> 233
€ -> 128
你有什么想法我可能遗漏了什么吗?
编辑1: 我刚刚通过读取sys.stdin进行了测试。这按预期工作:在cp850中,键入“é”会导致序数值为130。因此,问题确实只存在于命令行中。那么,命令行是否与标准输入处理方式不同?
编辑2: 看来我选错了关键字。我在SO上找到了另一个非常相似的主题:在Windows上使用Python 2.x从命令行参数读取Unicode字符。尽管如此,如果命令行未像sys.stdin一样编码,并且由于sys.getdefaultencoding()报告“ascii”,似乎没有办法知道它的实际编码。我认为使用win32扩展程序的答案相当巧妙。
locale.getpreferredencoding()
或在使用locale.setlocale()
后,使用locale.getlocale()[1]
可以获得正确的控制台和环境访问编码。尽管如此,在大多数现代系统中,硬编码UTF-8通常已经足够好了(因此它是最好的备用值)。 - Jacek Konieczny