为什么在Windows上使用Python 2.7打印时需要在Unicode字符前加空格?

7
我使用cmd Windows,chcp 65001,这是我的代码:
print u'\u0110 \u0110' + '\n'

结果:

 (a character cmd can't display) (character what i want)
 Traceback (most recent call last):
      File "b.py", line 26, in <module>
        print u'\u0110 \u0110'
    IOError: [Errno 2] No such file or directory

但是,当我使用这段代码时:
print u' \u0110 \u0110' + '\n'

结果:

(a space)(charecter what i want) (character what i want)
Traceback (most recent call last):
  File "b.py", line 26, in <module>
    print u' \u0110 \u0110' + '\n'
IOError: [Errno 2] No such file or directory

我的屏幕:

enter image description here

我的问题是:

  • 为什么Python 2.7在打印Unicode字符时需要加空格?

  • 如何修复IOError:[Errno 2]?


两者对我来说都可以。Python 2.7.3 - TankorSmash
我使用的是Windows,你呢?Linux? - pc43
是的,Ubuntu 12.04。也许文件编码有关? - TankorSmash
1
我认为问题出在 Windows 的命令行窗口。 - pc43
这看起来像是一个编码问题... - Zizouz212
显示剩余6条评论
2个回答

5
在Windows上,您可以使用print打印任意字符串(只要字体能够显示字符)。只需打印Unicode并配置您的环境即可。例如,print_unicode.py:
#!/usr/bin/env python
print(u'\u0110\u0110')

要在Windows控制台中打印内容,您可以使用win-unicode-console:

T:\> py -mpip install win-unicode-console
T:\> py -mrun print_unicode.py

不要忘记配置适当的控制台字体。在这种情况下,chcp的返回值并不重要。 您可以手动调用WriteConsoleW()函数(Unicode API),以将任意文本打印到Windows控制台。 您不需要第三方模块来将输出重定向到文件:
T:\> set PYTHONIOENCODING=utf-8
T:\> py print_unicode.py >output-utf-8.txt

注意:不使用run模块。它适用于Python 2和3。
如果您不需要打印非BMP Unicode字符,则可以使用Python IDLE来自stdlib,例如在Python 3中:
T:\> py -3 -midlelib -r print_unicode.py

IDLE也可在Python 2上使用,但调用方式不同。


5

简短回答

在 Windows 平台上,你不能使用 print 直接打印任意字符串。

有一些解决方案,在这里展示:如何让 Python 3 打印 UTF-8 编码的字符。但是,尽管那个问题的标题是如此,你不能使用这种方法来实际打印使用代码页 65001 的 UTF-8 编码,因为它在完成后会重复最后几个字节(如我在下面进一步描述)。

例如:

#! python2
import sys

enc = sys.stdout.encoding

def outputUnicode(t):
    bytes = t.encode(enc, 'replace')
    sys.stdout.write(bytes)

outputUnicode(u'The letter \u0110\n')

长答案

您可以使用 chcp 将控制台的代码页更改为包含要打印的字符的代码页。例如,在您的情况下,运行 chcp 852

如果我打印以下字符串,这是我的计算机上的结果。我正在使用代码页 850,这是英语系统的默认设置:

u"\u00abHello\u00bb"  # "«Hello»" 
u"\u0110"  # "Đ"
u"\u4f60\u597d"  # "你好"
u"a\u2192b\u2192c"  # "a→b→c"

第一条命令可以正常运行,因为所有字符都在代码页850中。接下来的三条命令将失败。 UnicodeEncodeError: 'charmap'编解码器无法在位置0编码字符u'\u0110':字符映射到<未定义> 将代码页更改为852,第二条命令将可正常运行。
虽然存在UTF-8代码页(65001),但它不能与Python 2.7一起使用。
在Python 3.4中,结果相同。如果将代码页更改为65001,您会得到略微不太正常的行为。 \Python34\python.exe -c "print(u'a\u2192b\u2192c')" a→b→c �c C:\> 额外的两个字符(�c)是Windows C标准库中的非标准行为的结果。它们是字符串的UTF-8编码中最后2个字节的重复。

我曾经使用过 chcp 65001,但仍然出现了错误,而且我无法在第一个字符之前打印空格。 - pc43
3
65001代码页存在问题,程序需要使用特殊技巧才能在此代码页上输出Unicode。 - roeland
对于熟悉C标准IO库的人来说:fwrite将返回字符串中字符的数量,而不是字节 - roeland
@PhamThanh 是的,当使用代码页65001时,这是另一个错误,而且在使用C的fwrite函数时也可以重现。 - roeland
无论 chcp 是什么,您都可以打印任意Unicode字符串。 - jfs
@J.F.Sebastian 哦,说得好。我没有考虑到覆盖标准输入(stdin)的问题。 - roeland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接