Python、Unicode和Windows控制台

Python、Unicode和Windows控制台,python,unicode,Python,Unicode,当我试图在Windows控制台中打印Unicode字符串时,我得到一个错误 unicodeincoder错误:“charmap”编解码器无法对字符进行编码…… 我认为这是因为Windows控制台不接受仅Unicode字符。最好的解决办法是什么? 有没有办法让Python自动打印?,而不是在这种情况下失败 编辑:我正在使用Python 2.5 注意:@LasseV.Karlsen带有复选标记的答案有点过时(从2008年开始)。请小心使用下面的解决方案/答案/建议 从今天(2016年1月6日)开始

当我试图在Windows控制台中打印Unicode字符串时,我得到一个错误

unicodeincoder错误:“charmap”编解码器无法对字符进行编码……

我认为这是因为Windows控制台不接受仅Unicode字符。最好的解决办法是什么? 有没有办法让Python自动打印
,而不是在这种情况下失败

编辑:我正在使用Python 2.5


注意:@LasseV.Karlsen带有复选标记的答案有点过时(从2008年开始)。请小心使用下面的解决方案/答案/建议


从今天(2016年1月6日)开始更为相关。

注意:这个答案有点过时(从2008年开始)。请小心使用下面的解决方案


这是一个详细说明问题和解决方案的页面(在该页面中搜索将sys.stdout包装到实例中的文本):

以下是该页面的代码摘录:

$ 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-c'导入系统、编解码器、语言环境;打印sys.stdout.encoding\
sys.stdout=codecs.getwriter(locale.getpreferredencoding())(sys.stdout)\
行=u“\u0411\n”;打印类型(行),透镜(行)\
系统标准输出写入(行);打印行'
UTF-8
2.
Б
Б
$python-c'导入系统、编解码器、语言环境;打印sys.stdout.encoding\
sys.stdout=codecs.getwriter(locale.getpreferredencoding())(sys.stdout)\
行=u“\u0411\n”;打印类型(行),透镜(行)\
系统标准输出写入(行);打印行“| cat”
没有一个
2.
Б
Б

该页面上还有更多信息,值得一读。

问题的原因是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

编辑:可以找到更多信息

下面的代码将使Python作为UTF-8输出到控制台,即使在Windows上也是如此

在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"

尽管其他听起来似乎合理的答案建议将代码页更改为65001,但这一点仍然存在。(另外,使用
sys.setdefaultencoding
更改默认编码也很重要。)


有关详细信息和确实有效的代码,请参阅。

如果您对获取坏字符的可靠表示不感兴趣,可以使用类似的方法(使用python>=2.6,包括3.x):


字符串中的坏字符将转换为可由Windows控制台打印的表示形式。

更新:实现:Windows上的默认控制台现在将接受所有Unicode字符。在内部,它使用与相同的Unicode API<代码>打印(unicode_字符串)现在应该可以工作了


我得到一个
unicodeincoder错误:“charmap”编解码器无法对字符进行编码…
错误

该错误意味着您尝试打印的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 看

有什么方法可以让我制作Python吗 自动打印
而不是在这种情况下失败

如果在您的情况下,用
替换所有不可编码的字符就足够了,那么您可以设置:


在Python3.6+中,交互式控制台缓冲区将忽略
PYTHONIOENCODING
envvar指定的编码,除非
PYTHONLEGACYWINDOWSIOENCODING
envvar设置为非空字符串。

与J.F.Sebastian的答案相关,但更直接

如果在打印到控制台/终端时遇到此问题,请执行以下操作:

>set PYTHONIOENCODING=UTF-8

就像Giampaolo Rodolá的回答,但更肮脏的是:我真的,真的打算花很长时间(很快)理解编码的整个主题,以及它们如何应用于Windoze控制台

目前我只想要sthg,这意味着我的程序不会崩溃,我明白。。。而且也不需要导入太多的外来模块(特别是我使用的是Jython,所以有一半的时间Python模块实际上是不可用的)

注意“pr”比“print”短(而且比“safeprint”短很多)

詹姆斯·苏拉克问道

有没有什么方法可以让Python自动打印一个文件?而不是在这种情况下失败

其他解决方案建议我们尝试修改Windows环境或替换Python的
print()
函数。下面的答案更接近于满足苏拉克的要求

在Windows 7下,可以使Python 3.5打印Unicode,而无需抛出
Unicode错误,如下所示:

代替:
打印(文本)

替换:
print(str(text).encode('utf-8'))

Python现在不再抛出异常,而是将不可打印的Unicode字符显示为\xNN十六进制代码,例如:

Halmalo n\xe2\x80\x99\xc3\xa9tait plus qu\xe2\x80\x99un黑点

而不是

Halmalo n'était加qu'un point noir

诚然,在其他条件相同的情况下,后者更可取,但在其他方面,前者对诊断完全准确
T:\> py -m pip install win-unicode-console
T:\> py -m run your_script.py
T:\> set PYTHONIOENCODING=:replace
T:\> python3 -c "print(u'[\N{EURO SIGN}]')"
[?]
>set PYTHONIOENCODING=UTF-8
def pr(s):
    try:
        print(s)
    except UnicodeEncodeError:
        for c in s:
            try:
                print( c, end='')
            except UnicodeEncodeError:
                print( '?', end='')
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 
print unicode(string, 'unicode-escape')
import os
string = "002 Could've Would've Should've"
os.system('echo ' + string)
pip install win-unicode-console
py -mrun your_script.py
print(yourstring.encode('ascii','replace'));
msg = s.recv(1024).decode("utf-8")
print(msg.encode('ascii','replace'));
chcp 65001 & set PYTHONIOENCODING=utf-8