我以为我对编码和Python了如指掌,但今天我遇到了一个奇怪的问题:尽管控制台设置为代码页850,Python报告正确,但我在命令行中输入的参数似乎是在代码页1252中编码的。如果我尝试用sys.stdin.encoding解码它们,我会得到错误的结果。如果我假设为“cp1252”,忽略sys.stdout.encoding报告的内容,它就可以工作。
是我遗漏了什么,还是这是Python中的一个bug?窗户?注意:我在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 "
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
Ç -> 128
虽然我希望第4个字符的序号值为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中,输入'e'将得到130的序数值。所以问题只在命令行。那么,命令行的处理方式是否与标准输入不同?
编辑2:似乎我的关键字不对。我发现另一个非常接近的话题是这样的:Read Unicode characters from command-line arguments in Python 2.x on Windows。不过,如果命令行不是像sys.stdin那样编码的,并且由于sys.getdefaultencoding()报告“ascii”,那么似乎无法知道它的实际编码。我发现使用win32扩展的答案相当老套。