我在Windows 8的CMD中,将代码页设置为65001(chcp 65001
)。我正在使用Python 2.7.2(ActivePython 2.7.2.5),并将PYTHONSTARTUP环境变量设置为"bootstrap.py"。
bootstrap.py:
import codecs
codecs.register(
lambda name: name == 'cp65001' and codecs.lookup('UTF-8') or None
)
这使我可以打印ASCII:
>>> print 'hello'
hello
>>> print u'hello'
hello
但是当我尝试打印一个包含非ASCII字符的Unicode字符串时,我得到的错误对我来说毫无意义。下面我尝试打印一些包含北欧符号的字符串(我在打印之间添加了额外的换行以便阅读):
>>> print u'æøå'
��øåTraceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory
>>> print u'åndalsnes'
��ndalsnes
>>> print u'åndalsnesæ'
��ndalsnesæTraceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 22] Invalid argument
>>> print u'Øst'
��st
>>> print u'uØst'
uØstTraceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 22] Invalid argument
>>> print u'ØstÆØÅæøå'
��stÆØÅæøåTraceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 22] Invalid argument
>>> print u'_ØstÆØÅæøå'
_ØstÆØÅæøåTraceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 22] Invalid argument
正如您所看到的,它并不总是会出现错误(甚至每次出错的错误都不相同),而且北欧符号只有偶尔能够正确显示。
有人能解释这种行为吗,或者至少帮我找出如何正确地在CMD中打印Unicode的方法吗?
codecs.code_page_encode
所使用,新的cp65001编解码器使用它来定义encode = functools.partial(codecs.code_page_encode, 65001)
,解码也是类似的。 - Eryk SunPRINT_ITEM
操作调用PyFile_WriteObject
,该函数调用PyObject_Print
,最终调用PyString_Type.tp_print
,使用 libcfwrite
向标准输出流 stdout 写入。问题在于一个 bug 会导致 stdout 的文件流的错误标志被设置,尽管没有发生任何错误(因此报告了随机的“错误”),因为write
返回写入的字符数而不是字节数。您可以通过使用os.write(sys.stdout.fileno(), s)
进行验证,其中s
是非 ASCII UTF-8 字符串。 - Eryk Sun_io.BufferedWriter
),底层的_io.FileIO
对目标文件描述符执行低级别的write
操作。 - Eryk Sun