Python,Unicode和Windows控制台

当我尝试在Windows控制台中打印Unicodestring时,出现UnicodeEncodeError: 'charmap' codec can't encode character ....错误。 我认为这是因为Windows控制台不接受只有Unicode的字符。 什么是最好的方法呢? 有什么办法可以让Python自动打印? 而不是在这种情况下失败?

编辑:我正在使用Python 2.5。


注意: @ LasseV.Karlsen答案与复选标记是有点过时(从2008年)。 请小心使用下面的解决scheme/答案/build议!

从今天(2016年1月6日)起, @JFSebastian的答案更具相关性。

注意:这个答案有些过时(从2008年)。 请小心使用下面的解决scheme!


这里是一个详细的问题和解决scheme的页面(search文本环绕sys.stdout的页面到一个实例 ):

PrintFails – Python Wiki

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

 $ 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 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 ,可以表示cp437 Unicode字符中的cp437字符:

  >>> u“\ N {EURO SIGN}”。encode('cp437')
回溯(最近一次通话最后):
 ...
 UnicodeEncodeError:'charmap'编解码器不能在位置0编码字符'\ u20ac':
字符映射到 

我认为这是因为Windows控制台不接受只有Unicode的字符。 什么是最好的方法呢?

Windows控制台不接受Unicode字符, 如果configuration了相应的字体 ,它甚至可以显示它们(仅限 BMP)。 WriteConsoleW() API应按照@Daira Hopwood的回答build议使用。 它可以被透明地调用,即如果你使用win-unicode-console包 ,你不需要也不应该修改你的脚本:

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

看看Python 3.4,Unicode,不同的语言和Windows有什么关系?

有什么办法可以让Python自动打印? 而不是在这种情况下失败?

如果足以将所有不可编码的字符replace为? 在你的情况,那么你可以设置PYTHONIOENCODING envvar :

 T:\> set PYTHONIOENCODING=:replace T:\> python3 -c "print(u'[\N{EURO SIGN}]')" [?] 

在Python 3.6+中,除非PYTHONLEGACYWINDOWSIOENCODING envvar设置为非空string,否则对于交互式控制台缓冲区,由PYTHONIOENCODING envvar指定的编码将被忽略。

尽pipe其他合理的答案,build议将代码页更改为65001,这是行不通的 。 (另外,使用sys.setdefaultencoding更改默认编码不是一个好主意 。)

看到这个问题的细节和代码,确实工作。

如果你不想获得可靠的坏字符表示,你可以使用类似的东西(使用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}") 

string中的错误字符将被转换为可由Windows控制台打印的表示forms。

下面的代码将使Python输出到UTF-8,即使在Windows上。

控制台将在Windows 7上很好地显示字符,但是在Windows XP上它不能很好地显示它们,但至less它能够正常工作,而且最重要的是,在所有平台上,脚本都将具有一致的输出。 您将能够将输出redirect到一个文件。

下面的代码在Windows上用Python 2.6进行了testing。

 #!/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" 

就像GiampaoloRodolà的回答一样,但更加肮脏:我确实打算花很长时间(很快)来理解整个编码主题,以及它们如何应用于Windoze控制台,

就目前来说,我只是想要sthg,这意味着我的程序不会被破坏,而且我也明白了…也不涉及导入太多奇特的模块(特别是我使用Jython,所以有一半是Python模块事实上不可用)。

 def pr(s): try: print(s) except UnicodeEncodeError: for c in s: try: print( c, end='') except UnicodeEncodeError: print( '?', end='') 

NB“PR”比“打印”短(types比“safeprint”短得多)…!

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控制台窗口的顶部,在选项卡fontselect了lucida控制台。

对于Python 2,请尝试:
打印unicode(string,'unicode-escape')

对于Python 3,请尝试:
import操作系统
string='002可能应该会'
os.system('echo'+ string)

或者试试win-unicode-console:
pip安装win-unicode-console
py -mrun your_script.py

你的问题的原因是不是 Win的控制台不愿意接受Unicode(因为它是这样做的,因为我猜Win2k的默认情况下)。 这是默认的系统编码。 试试这段代码,看看它给了你什么:

 import sys sys.getdefaultencoding() 

如果它说ascii,这是你的原因;-)你必须创build一个名为sitecustomize.py文件,并把它放在pythonpath下(我把它放在/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书中find

JF Sebastian的回答有点类似,但更直接。

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

 >set PYTHONIOENCODING=UTF-8 

James Sulak问,

有什么办法可以让Python自动打印? 而不是在这种情况下失败?

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

在Windows 7下,可以使Python 3.5打印Unicode而不抛出UnicodeEncodeError ,如下所示:

取代: print(text)
substitute: print(str(text).encode('utf-8'))

Python不会抛出exception,而是将不可打印的Unicode字符显示为\ xNNhex代码,例如:

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

代替

Halmalon'était加qu'un点黑色

当然,后者更可取,但前者对于诊断信息是完全准确的。 因为它将Unicode显示为文字字节值,所以前者也可以帮助诊断编码/解码问题。

注意:上面str()调用是需要的,否则encode()会导致Python拒绝Unicode字符作为数字元组。