Python,Unicode和Windows控制台

时间:2008-08-07 22:26:58

标签: python unicode

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

编辑:我正在使用Python 2.5。


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

截至今天(2016年1月6日),

@JFSebastian answer更具相关性。

14 个答案:

答案 0 :(得分:66)

更新: Python 3.6实施PEP 528: Change Windows console encoding to UTF-8 Windows上的默认控制台现在将接受所有Unicode字符。在内部,它使用相同的Unicode API为the win-unicode-console package mentioned belowprint(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?

  

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

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

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

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

答案 1 :(得分:33)

注意:这个答案有点过时(从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 :(得分:27)

尽管有其他看似合理的答案,建议将代码页更改为65001,does not work。 (另外,使用sys.setdefaultencoding更改默认编码为not a good idea。)

有关可行的详细信息和代码,请参阅this question

答案 3 :(得分:14)

如果您对获得可靠的不良角色表示不感兴趣,可以使用类似的东西(使用python&gt; = 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控制台可打印的表示形式进行转换。

答案 4 :(得分:10)

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

答案 5 :(得分:4)

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

chcp 65001 & set PYTHONIOENCODING=utf-8

答案 6 :(得分:4)

就像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”的类型比“print”短(并且键入的时间比“safeprint”短得多)...!

答案 7 :(得分:3)

对于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-console:

pip install win-unicode-console
py -mrun your_script.py

答案 8 :(得分:2)

TL; DR:

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

我自己遇到了这个问题,正在使用Twitch聊天(IRC)机器人。 (最新的Python 2.7)

我想解析聊天消息以便回复...

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

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

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

这更正了漫游器引发UnicodeEncodeError: 'charmap'错误的问题,并用?替换了unicode字符。

答案 9 :(得分: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

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

答案 10 :(得分:1)

与F. F. Sebastian的答案有关,但更直接。

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

>set PYTHONIOENCODING=UTF-8

答案 11 :(得分:1)

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

答案 12 :(得分:0)

James Sulak问道,

  

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

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

在Windows 7下,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 point noir

而不是

Halmalon'était加上qu'un point noir

当然,后者更适合 ceteris paribus ,但除此之外,前者对诊断信息完全准确。因为它将Unicode显示为文字字节值,所以前者也可以帮助诊断编码/解码问题。

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

答案 13 :(得分:0)

问题在于 windows 默认编码设置为 cp1252,需要设置为 utf-8。 (check PEP)

使用以下方法检查默认编码:

var connectionString = $"Host=postgresql_database;Port=5432;Database=databasename;Username=username;Password=password";

您可以覆盖区域设置

import locale 
locale.getpreferredencoding()

来自stack link的引用代码