如何在Windows 8上用Python 3.4打印UTF-8到控制台?
我正在尝试从一个Python模块在Windows控制台中打印UTF-8的扑克牌符号(♠,♥,♦︎︎,♣)。我使用的控制台是git bash,并且用console2作为前端。我尝试了下面的几种方法,但到目前为止都没有成功。
确保控制台可以处理UTF-8字符。
这两个测试让我相信,控制台本身不是问题所在。尝试从Python模块执行相同的操作。
当我运行.py文件时,结果是这样的。print(u'♠') UnicodeEncodeError: 'charmap' codec can't encode character '\u2660' in position 0: character maps to <undefined>
尝试对♠进行编码。
这让我得到了用UTF-8编码的Unicode集合,但仍然没有得到黑桃符号。text = '♠' print(text.encode('utf-8')) b'\xe2\x99\xa0'
我感觉我可能漏掉了某个步骤,或者对整个编码/解码的过程理解得不够透彻。我阅读了这篇、这篇和这篇。最后一篇文章建议将sys.stdout包装到代码中,但这篇文章说使用stdout是多余的,并指向了另一个使用codecs模块的页面。
6 个回答
我也遇到过和你一样的问题,使用的是Python 3.6。不过,我通过升级到Python 3.7解决了这个问题。所以,你只需要更新一下你的Python版本就可以了。
你可以这样理解:字符串是字符的一个序列,而不是字节的序列。字符是Unicode编码点,字节只是0到255之间的数字。在计算机底层,实际上是通过字节序列来工作的。如果你想在Python中打印一个字符串,只需要调用 print(a_string)
。但为了和操作系统进行交流,这个字符串必须被编码成字节序列。这一过程在 print
函数的内部自动完成。使用的编码方式是 sys.stdout.encoding
。如果你遇到 UnicodeEncodeError
,那就意味着你的字符无法用当前的编码方式进行编码。
据我所知,目前在Windows上运行Python时,使用的编码方式并不能编码所有字符(像UTF-8或UTF-16),而Python假设的编码和操作系统实际使用的编码在输入和输出上并不一致。不过有一个解决办法,你可以使用 win_unicode_console
这个包,它旨在解决这个问题。只需通过 pip install win_unicode_console
安装它,然后在你的 sitecustomize
文件中导入并调用 win_unicode_console.enable()
。这将作为一个外部补丁来修复你Python安装中的这个问题。想了解更多信息,可以查看文档:https://github.com/Drekin/win-unicode-console。
我想做的是从一个Python模块向Windows控制台打印UTF-8的扑克牌符号(♠,♥,♦,♣)。
UTF-8是一种将Unicode字符转换成字节的编码方式。♠♥♦♣是Unicode字符,可以用多种编码方式表示,而UTF-8就是其中一种。作为一种UTF编码,UTF-8可以表示任何Unicode字符。但这些符号本身并没有什么特别的“UTF-8”之处。
其他可以表示♠♥♦♣的编码包括Windows的850代码页和437代码页,你的控制台在西欧版Windows下可能会使用这些编码。你可以在这些编码中打印♠,但这并不是通过UTF-8来实现的,而且你也无法使用UTF-8中存在但在这些代码页之外的其他Unicode字符。
print(u'♠')
UnicodeEncodeError: 'charmap' codec can't encode character '\u2660'
在Python 3中,这和你上面做的print('♠')
测试是一样的,所以你在调用包含这个print
的脚本时,和你的py -3.4
有些不同。你从脚本中得到的sys.stdout.encoding
是什么?
为了让print
正常工作,你需要确保Python使用正确的编码。如果它没有从终端设置中正确识别编码,你确实需要将PYTHONIOENCODING
设置为cp437
。
>>> text = '♠'
>>> print(text.encode('utf-8'))
b'\xe2\x99\xa0'
print
只能打印Unicode字符串。对于其他类型的字符串,比如通过encode()
方法得到的bytes
字符串,它会得到对象的字面表示(repr
)。b'\xe2\x99\xa0'
就是你在Python 3中写一个包含UTF-8编码♠的字节字面量的方式。
如果你想绕过print
默认使用的PYTHONIOENCODING编码,使用你自己的编码,可以这样做:
>>> import sys
>>> sys.stdout.buffer.write('♠'.encode('cp437'))
当然,这样做会导致在不使用437代码页的控制台上输出错误(例如非西欧版的安装)。一般来说,对于像Python这样的使用C标准输入输出的应用程序,将非ASCII字符输出到Windows控制台是非常不可靠的,不值得去尝试。
从Python 3.7.x开始,你可以重新设置标准输出(stdout):
import sys
sys.stdout.reconfigure(encoding='utf-8')