[英]Python, Unicode, and the Windows console
当我尝试在 Windows 控制台中打印 Unicode 字符串时,出现错误。
UnicodeEncodeError: 'charmap' codec can't encode character....
我认为这是因为 Windows 控制台不接受纯 Unicode 字符。 最好的解决方法是什么? 有什么办法可以让 Python 自动打印 a ?
而不是在这种情况下失败?
编辑:我正在使用 Python 2.5。
注意: @LasseV.Karlsen 带有复选标记的答案有点过时(从 2008 年开始)。 请谨慎使用下面的解决方案/答案/建议!!
截至今天(2016 年 1 月 6 日), @JFSebastian 的回答更为相关。
更新: Python 3.6实现PEP 528:将 Windows 控制台编码更改为 UTF-8 : Windows 上的默认控制台现在将接受所有 Unicode 字符。 在内部,它使用与下面提到的win-unicode-console
包相同的 Unicode API。 print(unicode_string)
现在应该可以工作了。
我收到
UnicodeEncodeError: 'charmap' codec can't encode character...
错误。
该错误意味着您尝试打印的 Unicode 字符无法使用当前 ( chcp
) 控制台字符编码来表示。 代码页通常是 8 位编码,例如cp437
,它只能表示 ~1M Unicode 字符中的 ~0x100 个字符:
>>> u"\N{EURO SIGN}".encode('cp437') Traceback (most recent call last): ... UnicodeEncodeError: 'charmap' codec can't encode character '\u20ac' in position 0: character maps to
我认为这是因为 Windows 控制台不接受 Unicode-only 字符。 解决这个问题的最佳方法是什么?
Windows 控制台确实接受 Unicode 字符,如果配置了相应的字体,它甚至可以显示它们(仅 BMP)。 应按照@Daira Hopwood 的回答中的建议使用WriteConsoleW()
API。 它可以透明地调用,即,如果您使用win-unicode-console
包,则不需要也不应该修改您的脚本:
T:\> py -m pip install win-unicode-console
T:\> py -m run your_script.py
请参阅Python 3.4、Unicode、不同语言和 Windows 有什么关系?
有什么办法可以让Python自动打印一个
?
而不是在这种情况下失败?
如果用?
替换所有无法编码的字符就足够了?
在您的情况下,您可以设置PYTHONIOENCODING
envvar :
T:\> set PYTHONIOENCODING=:replace
T:\> python3 -c "print(u'[\N{EURO SIGN}]')"
[?]
在 Python 3.6+ 中,交互式控制台缓冲区会忽略PYTHONIOENCODING
envvar 指定的编码,除非PYTHONLEGACYWINDOWSIOENCODING
envvar 设置为非空字符串。
注意:这个答案有点过时了(从 2008 年开始)。 请谨慎使用以下解决方案!!
这是一个详细说明问题和解决方案的页面(在页面中搜索文本Wrapping sys.stdout into an instance ):
这是该页面的代码摘录:
$ python -c 'import sys, codecs, locale; print sys.stdout.encoding; \
sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout); \
line = u"\u0411\n"; print type(line), len(line); \
sys.stdout.write(line); print line'
UTF-8
<type 'unicode'> 2
Б
Б
$ python -c 'import sys, codecs, locale; print sys.stdout.encoding; \
sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout); \
line = u"\u0411\n"; print type(line), len(line); \
sys.stdout.write(line); print line' | cat
None
<type 'unicode'> 2
Б
Б
该页面上还有更多信息,非常值得一读。
如果您对获得坏字符的可靠表示不感兴趣,您可以使用这样的方法(使用 python >= 2.6,包括 3.x):
from __future__ import print_function
import sys
def safeprint(s):
try:
print(s)
except UnicodeEncodeError:
if sys.version_info >= (3,):
print(s.encode('utf8').decode(sys.stdout.encoding))
else:
print(s.encode('utf8'))
safeprint(u"\N{EM DASH}")
字符串中的坏字符将转换为 Windows 控制台可打印的表示形式。
即使在 Windows 上,以下代码也会使 Python 输出到控制台为 UTF-8。
控制台将在 Windows 7 上很好地显示字符,但在 Windows XP 上它不会很好地显示它们,但至少它可以工作,最重要的是,您将在所有平台上从脚本中获得一致的输出。 您将能够将输出重定向到文件。
下面的代码在 Windows 上使用 Python 2.6 进行了测试。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import codecs, sys
reload(sys)
sys.setdefaultencoding('utf-8')
print sys.getdefaultencoding()
if sys.platform == 'win32':
try:
import win32console
except:
print "Python Win32 Extensions module is required.\n You can download it from https://sourceforge.net/projects/pywin32/ (x86 and x64 builds are available)\n"
exit(-1)
# win32console implementation of SetConsoleCP does not return a value
# CP_UTF8 = 65001
win32console.SetConsoleCP(65001)
if (win32console.GetConsoleCP() != 65001):
raise Exception ("Cannot set console codepage to 65001 (UTF-8)")
win32console.SetConsoleOutputCP(65001)
if (win32console.GetConsoleOutputCP() != 65001):
raise Exception ("Cannot set console output codepage to 65001 (UTF-8)")
#import sys, codecs
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
sys.stderr = codecs.getwriter('utf8')(sys.stderr)
print "This is an Е乂αmp١ȅ testing Unicode support using Arabic, Latin, Cyrillic, Greek, Hebrew and CJK code points.\n"
就像 Giampaolo Rodolà 的回答一样,但更肮脏:我真的,真的打算花很长时间(很快)了解编码的整个主题以及它们如何应用于 Windoze 控制台,
目前我只想要 sthg 这意味着我的程序不会崩溃,而且我理解......而且它不涉及导入太多外来模块(特别是我使用的是 Jython,所以有一半的时间是 Python模块实际上并不可用)。
def pr(s):
try:
print(s)
except UnicodeEncodeError:
for c in s:
try:
print( c, end='')
except UnicodeEncodeError:
print( '?', end='')
注意“pr”比“print”更短(并且比“safeprint”更短)......!
只需在执行 python 脚本之前在命令行中输入此代码:
chcp 65001 & set PYTHONIOENCODING=utf-8
对于 Python 2 尝试:
print unicode(string, 'unicode-escape')
对于 Python 3,请尝试:
import os
string = "002 Could've Would've Should've"
os.system('echo ' + string)
或者试试 win-unicode-console:
pip install win-unicode-console
py -mrun your_script.py
与 JF Sebastian 的回答有点相关,但更直接。
如果您在打印到控制台/终端时遇到此问题,请执行以下操作:
>set PYTHONIOENCODING=UTF-8
特尔;博士:
print(yourstring.encode('ascii','replace'));
我自己遇到了这个问题,正在开发 Twitch 聊天 (IRC) 机器人。 (Python 2.7 最新)
我想解析聊天消息以便回复...
msg = s.recv(1024).decode("utf-8")
但也要以人类可读的格式将它们安全地打印到控制台:
print(msg.encode('ascii','replace'));
这纠正了机器人抛出UnicodeEncodeError: 'charmap'
错误的问题,并将 unicode 字符替换为?
.
问题的原因不是Win 控制台不愿意接受 Unicode(因为我猜默认情况下是 Win2k,所以它会这样做)。 它是默认的系统编码。 试试这个代码,看看它给了你什么:
import sys
sys.getdefaultencoding()
如果它说 ascii,那就是你的原因;-) 你必须创建一个名为 sitecustomize.py 的文件并将它放在 python 路径下(我把它放在 /usr/lib/python2.5/site-packages 下,但这是不同的Win - 它是 c:\\python\\lib\\site-packages 或其他东西),内容如下:
import sys
sys.setdefaultencoding('utf-8')
也许您可能还想在文件中指定编码:
# -*- coding: UTF-8 -*-
import sys,time
编辑:更多信息可以在优秀的 Dive into Python 书中找到
Python 3.6 windows7:有几种启动python的方法,你可以使用python控制台(上面有一个python标志)或windows控制台(上面写着cmd.exe)。
我无法在 Windows 控制台中打印 utf8 字符。 打印 utf-8 字符会引发此错误:
OSError: [winError 87] The paraneter is incorrect
Exception ignored in: (_io-TextIOwrapper name='(stdout)' mode='w' ' encoding='utf8')
OSError: [WinError 87] The parameter is incorrect
在尝试并未能理解上述答案后,我发现这只是一个设置问题。 右键单击 cmd 控制台窗口的顶部,在选项卡font
选择 lucida 控制台。
詹姆斯·苏拉克问道,
有什么办法可以让 Python 自动打印一个 ? 而不是在这种情况下失败?
其他解决方案建议我们尝试修改 Windows 环境或替换 Python 的print()
函数。 下面的答案更接近于满足 Sulak 的要求。
在 Windows 7 下,Python 3.5 可以打印 Unicode 而不会抛出UnicodeEncodeError
如下:
代替: print(text)
替代: print(str(text).encode('utf-8'))
Python 现在不再抛出异常,而是将不可打印的 Unicode 字符显示为\\xNN十六进制代码,例如:
Halmalo n\\xe2\\x80\\x99\\xc3\\xa9tait plus qu\\xe2\\x80\\x99un point noir
代替
Halmalo n'était plus qu'un point noir
当然,在其他条件不变的情况下,后者更可取,但除此之外,前者对于诊断消息是完全准确的。 因为它将 Unicode 显示为文字字节值,所以前者还可以帮助诊断编码/解码问题。
注意:上面的str()
调用是必需的,否则encode()
会导致 Python 拒绝将 Unicode 字符作为数字元组。
如今, Windows 控制台不会遇到此错误,除非您重定向 output 。
这是一个示例 Python 脚本scratch_1.py
:
s = "∞"
print(s)
如果您按如下方式运行脚本,一切都会按预期进行:
python scratch_1.py
∞
但是,如果您运行以下命令,则会收到与问题中相同的错误:
python scratch_1.py > temp.txt
Traceback (most recent call last):
File "C:\Users\Wok\AppData\Roaming\JetBrains\PyCharmCE2022.2\scratches\scratch_1.py", line 3, in <module>
print(s)
File "C:\Users\Wok\AppData\Local\Programs\Python\Python311\Lib\encodings\cp1252.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_table)[0]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
UnicodeEncodeError: 'charmap' codec can't encode character '\u221e' in position 0: character maps to <undefined>
要按照原始问题中的建议解决此问题,即用问号替换错误字符?
, 可以进行如下操作:
s = "∞"
try:
print(s)
except UnicodeEncodeError:
output_str = s.encode("ascii", errors="replace").decode("ascii")
print(output_str)
这很重要:
decode()
,以便 output 的类型是str
而不是bytes
,"ascii"
,以避免创建mojibake 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.