当我尝试在Windows控制台中打印Unicode字符串时,出现UnicodeEncodeError: 'charmap' codec can't encode character ....错误。 我认为这是因为Windows控制台不接受仅Unicode字符。 最好的方法是什么? 有什么方法可以让Python自动打印?而不是在这种情况下失败?
编辑:我正在使用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)现在应该正常工作。
I get a UnicodeEncodeError: 'charmap' codec can't encode character... error.
该错误意味着您尝试打印的Unicode字符无法使用当前(chcp)控制台字符编码表示。代码页通常是8位编码,例如cp437,它只能表示来自?1M个Unicode字符的~0x100个字符:
1 2 3 4 5 6
| >>> u"
{EURO SIGN}".encode('cp437')
Traceback (most recent call last):
...
UnicodeEncodeError: 'charmap' codec can't encode character '\u20ac' in position 0:
character maps to |
I assume this is because the Windows console does not accept Unicode-only characters. What's the best way around this?
Windows控制台确实接受Unicode字符,如果配置了相应的字体,它甚至可以显示它们(仅限BMP)。 WriteConsoleW() API应该按照@Daira Hopwood的回答中的建议使用。它可以透明地调用,即如果使用win-unicode-console包,则不需要也不应该修改脚本:
1 2
| Tamp;gt; py -mpip install win-unicode-console
Tamp;gt; py -mrun your_script.py |
请参阅Python 3.4,Unicode,不同语言和Windows有什么用?
Is there any way I can make Python
automatically print a ? instead of failing in this situation?
如果在您的情况下用?替换所有不可编码的字符就足够了,那么您可以设置PYTHONIOENCODING envvar:
1 2 3 4
| Tamp;gt; set PYTHONIOENCODING=:replace
Tamp;gt; python3 -c"print(u'[
{EURO SIGN}]')"
[?] |
在Python 3.6+中,除非将PYTHONLEGACYWINDOWSIOENCODING envvar设置为非空字符串,否则将忽略由PYTHONIOENCODING envvar指定的编码以用于交互式控制台缓冲区。
注意:这个答案有点过时(从2008年开始)。请小心使用以下解决方案!!
这是一个详细说明问题的页面和解决方案(在页面中搜索将sys.stdout包装到实例中的文本):
PrintFails - Python Wiki
这是该页面的代码摘录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| $ python -c 'import sys, codecs, locale; print sys.stdout.encoding; \
sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout); \
line = u"\u0411
"; 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
"; print type(line), len(line); \
sys.stdout.write(line); print line' | cat
None
<type 'unicode'> 2
Б
Б |
有关该页面的更多信息,非常值得一读。
尽管有其他看似合理的答案建议将代码页更改为65001,但这不起作用。 (另外,使用sys.setdefaultencoding更改默认编码不是一个好主意。)
有关详细信息和可行的代码,请参阅此问题。
如果你对获得可靠的坏字符表示不感兴趣,可以使用类似的东西(使用python> = 2.6,包括3.x):
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from __future__ import print_function
import sys
def safeprint(s):
try:
print(s)
except UnicodeEncodeError:
if sys.version_inamp;gt;= (3,):
print(s.encode('utf8').decode(sys.stdout.encoding))
else:
print(s.encode('utf8'))
safeprint(u"
{EM DASH}") |
字符串中的错误字符将以Windows控制台可打印的表示形式进行转换。
下面的代码将使Python输出到控制台,即使在Windows上也是UTF-8。
控制台将在Windows 7上很好地显示字符,但在Windows XP上它将无法很好地显示它们,但至少它将起作用,最重要的是,您将在所有平台上从脚本获得一致的输出。您将能够将输出重定向到文件。
下面的代码在Windows上使用Python 2.6进行了测试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #!/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.
You can download it from https://sourceforge.net/projects/pywin32/ (x86 and x64 builds are available)
"
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.
" |
只需在执行python脚本之前在命令行中输入此代码:
1
| chcp 650amp; set PYTHONIOENCODING=utf-8 |
就像GiampaoloRodolà的答案一样,但更肮脏:我真的,真的打算花很长时间(很快)理解编码的整个主题以及它们如何应用于Windoze控制台,
目前我只想要sthg这意味着我的程序不会崩溃,而且我理解...而且还没有涉及导入太多异国情调的模块(特别是我使用的是Jython,所以有一半时间是Python事实证明,模块并不可用。
1 2 3 4 5 6 7 8 9
| def pr(s):
try:
print(s)
except UnicodeEncodeError:
for c in s:
try:
print( c, end='')
except UnicodeEncodeError:
print( '?', end='') |
NB"pr"的类型比"print"短(并且输入的类型比"safeprint"短得多)......!
对于Python 2,请尝试:
1
| print unicode(string, 'unicode-escape') |
对于Python 3,请尝试:
1 2 3
| import os
string ="002 Could've Would've Should've"
os.system('echo ' + string) |
或者尝试win-unicode-console:
1 2
| pip install win-unicode-console
py -mrun your_script.py |
TL; DR:
1
| print(yourstring.encode('ascii','replace')); |
我自己遇到了这个,在Twitch聊天(IRC)机器人上工作。 (Python 2.7最新)
我想解析聊天消息以便回复...
1
| msg = s.recv(1024).decode("utf-8") |
但也要以人类可读的格式将它们安全地打印到控制台:
1
| print(msg.encode('ascii','replace')); |
这纠正了机器人抛出UnicodeEncodeError: 'charmap'错误的问题,并用?替换了unicode字符。
你的问题的原因不是Win控制台不愿意接受Unicode(因为我这样做,因为我猜默认为Win2k)。它是默认的系统编码。试试这段代码,看看它给你的东西:
1 2
| import sys
sys.getdefaultencoding() |
如果它说ascii,那是你的原因;-)
你必须创建一个名为sitecustomize.py的文件并将其放在python路径下(我把它放在/usr/lib/python2.5/site-packages下,但这在Win上是不同的 - 它是c: python lib site-packages或者其他东西),包含以下内容:
1 2
| import sys
sys.setdefaultencoding('utf-8') |
也许您可能还想在文件中指定编码:
1 2
| # -*- coding: UTF-8 -*-
import sys,time |
编辑:更多信息可以在优秀的Dive into Python书中找到
Python 3.6 windows7:有几种启动python的方法,你可以使用python控制台(上面有python标识)或windows控制台(它上面写有cmd.exe)。
我无法在Windows控制台中打印utf8字符。打印utf-8字符会给我这个错误:
1 2 3
| 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控制台。
有点像J. F. Sebastian的答案,但更直接。
如果在打印到控制台/终端时遇到此问题,请执行以下操作:
1
| set PYTHONIOENCODING=UTF-8 |
詹姆斯苏拉克问道,
Is there any way I can make Python automatically print a ? instead of failing in this situation?
其他解决方案建议我们尝试修改Windows环境或替换Python的print()函数。下面的答案更接近满足Sulak的要求。
在Windows 7下,可以使用Python 3.5打印Unicode而不抛出UnicodeEncodeError,如下所示:
print(text)
print(str(text).encode('utf-8'))
Python现在将不可打印的Unicode字符显示为 xNN十六进制代码,而不是抛出异常,例如:
代替
当然,后者在其他条件不变的情况下是优选的,但是前者对于诊断信息是完全准确的。因为它将Unicode显示为文字字节值,所以前者也可以帮助诊断编码/解码问题。
注意:需要上面的str()调用,否则encode()会导致Python拒绝将Unicode字符作为数字元组。