代码之家  ›  专栏  ›  技术社区  ›  James Sulak

python、unicode和windows控制台

  •  118
  • James Sulak  · 技术社区  · 17 年前

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

    编辑: 我使用的是python 2.5。


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

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

    13 回复  |  直到 17 年前
        1
  •  33
  •   alvas    9 年前

    注: 这个答案有点过时(从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
      Б
      Б
    

    那页上有更多的信息,值得一读。

        2
  •  57
  •   Community CDub    8 年前

    更新: Python 3.6 器具 PEP 528: Change Windows console encoding to UTF-8 : Windows上的默认控制台现在将接受所有Unicode字符。 在内部,它使用与 the win-unicode-console package mentioned below . 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字符。最好的方法是什么?

    Windows控制台不接受Unicode字符,甚至可以显示它们(仅限BMP) 如果配置了相应的字体 . WriteConsoleW() 应按照中的建议使用API。 @Daira Hopwood's answer . 它可以透明地调用,也就是说,如果使用 win-unicode-console package :

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

    What's the deal with Python 3.4, Unicode, different languages and Windows?

    我能做蟒蛇吗 自动打印 ? 而不是在这种情况下失败?

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

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

    在python 3.6+中,由 肾盂编码 对于交互式控制台缓冲区,将忽略envvar,除非 PYTHONLEGACYWINDOWSIOENCODING envvar设置为非空字符串。

        3
  •  26
  •   Community CDub    8 年前

    尽管其他听起来似乎合理的答案建议将代码页更改为65001,但是 does not work . (另外,更改默认编码时使用 sys.setdefaultencoding not a good idea )

    this question 详细信息和代码。

        4
  •  14
  •   Giampaolo Rodolà    13 年前

    如果您不想获得坏字符的可靠表示,可以使用类似的方法(使用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控制台打印的表示形式。

        5
  •  10
  •   sorin    12 年前

    下面的代码将使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"
    
        6
  •  4
  •   mike rodent    9 年前

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

    就目前而言,我只想做一件事,这意味着我的程序不会崩溃,我明白…而且,这并不涉及导入太多的外来模块(特别是我使用的是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”短得多)…!

        7
  •  3
  •   Akshay shubaly    7 年前

    对于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控制台:

    pip install win-unicode-console
    py -mrun your_script.py
    
        8
  •  2
  •   martineau    12 年前

    你的问题是 不是 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
    

    编辑:可以找到更多信息 in excellent the Dive into Python book

        9
  •  2
  •   c97    6 年前

    在执行python脚本之前,只需在命令行中输入以下代码:

    chcp 65001 & set PYTHONIOENCODING=utf-8
    
        10
  •  1
  •   Kinjal Dixit    9 年前

    关于J.F.塞巴斯蒂安的回答有点关联,但更直接。

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

    >set PYTHONIOENCODING=UTF-8
    
        11
  •  1
  •   J. Does    8 年前

    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 
    

    在尝试了并且没有理解上面的答案之后,我发现这只是一个设置问题。右键单击命令控制台窗口顶部的选项卡 font 选择Lucida控制台。

        12
  •  1
  •   Matthew Estock    7 年前

    DR:

    print(yourstring.encode('ascii','replace'));
    

    我自己也遇到了这个问题,在一个twitch chat(IRC)机器人上工作。(最新的python 2.7)

    我想分析聊天信息以回应…

    msg = s.recv(1024).decode("utf-8")
    

    但也要以人类可读的格式安全地将它们打印到控制台上:

    print(msg.encode('ascii','replace'));
    

    这纠正了机器人抛出的问题 UnicodeEncodeError: 'charmap' 错误,并将Unicode字符替换为 ? .

        13
  •  0
  •   CODE-REaD    9 年前

    詹姆斯·苏拉克问,

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

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

    在Windows7下,可以让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点噪声

    而不是

    哈马洛-纳提加群点-诺瓦

    当然,后者更可取 其他条件相同 否则,前者对于诊断消息是完全准确的。因为它将Unicode显示为文本字节值,所以前者还可以帮助诊断编码/解码问题。

    注: 这个 str() 需要以上调用,否则 encode() 使python拒绝将unicode字符作为数字的元组。