Python,Unicode和Windows控制台

时间:2020-03-05 18:38:29  来源:igfitidea点击:

当我尝试在Windows控制台中打印Unicode字符串时,出现UnicodeEncodeError:'charmap'编解码器无法编码字符....错误。我认为这是因为Windows控制台不接受仅Unicode字符。最好的办法是什么?有什么方法可以使Python自动打印?`而不是在这种情况下失败?

编辑:我正在使用Python 2.5.

注意:带有对勾标记的@ LasseV.Karlsen答案有些过时(自2008年起)。请谨慎使用以下解决方案/答案/建议!!

截至今天(2016年1月6日),@ JFSebastian的答案更加相关。

解决方案

回答

注意:这个答案有点过时了(从2008年开始)。请谨慎使用以下解决方案!!

这是详细描述问题和解决方案的页面(在页面中将文本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
  Б
  Б

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

回答

我们出现问题的原因不是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》一书中找到

回答

以下代码即使在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"