UnicodeEncodeError: 'charmap'编解码器无法编码-字符映射为,print函数。
UnicodeEncodeError: 'charmap'编解码器无法编码-字符映射为,print函数。
我正在编写一个Python(Python 3.3)程序,使用POST方法将一些数据发送到网页。在调试过程中,我通常会获取页面结果并使用print()函数将其显示在屏幕上。
代码如下:
conn.request("POST", resource, params, headers)
response = conn.getresponse()
print(response.status, response.reason)
data = response.read()
print(data.decode('utf-8'));
HTTPResponse .read()方法返回一个编码为字节的元素,编码为一个格式良好的UTF-8文档。这在我停止使用Windows的IDLE GUI并改用Windows控制台后出现了问题。返回的页面中有一个U+2014字符(长破折号),在Windows GUI中print函数可以很好地转换(我假设是Code Page 1252),但在Windows控制台(Code Page 850)中无法转换。由于默认的strict行为,我得到以下错误:
UnicodeEncodeError: 'charmap' codec can't encode character '\u2014' in position 10248: character maps to
我可以使用下面这段相当丑陋的代码来解决这个问题:
print(data.decode('utf-8').encode('cp850','replace').decode('cp850'))
现在它将有问题的字符“—”替换为一个问号。这不是理想的情况(破折号应该是一个更好的替换),但对于我的目的来说已经足够了。
我对我的解决方案有几个不满意的地方。
1. 这段代码很丑陋,涉及到了所有的解码、编码和解码。
2. 它只解决了这个特定的情况。如果我将程序移植到使用其他编码(latin-1、cp437、再回到cp1252等)的系统上,它应该能够识别目标编码。但实际上它不能。(例如,当再次使用IDLE GUI时,破折号也丢失了,而之前没有发生这种情况)
3. 如果长破折号能够转换为连字符而不是问号,那就更好了。
问题不是长破折号(我可以想出解决这个特定问题的几种方法),而是我需要编写健壮的代码。我正在使用来自数据库的数据填充页面,而这些数据可能会返回。我可以预见到许多其他冲突的情况:一个'Á' U+00c1(在我的数据库中可能存在)可以转换为CP-850(用于西欧语言的DOS/Windows控制台编码),但不能转换为CP-437(用于美国英语的编码,是许多Windows安装的默认编码)。
所以,问题是:
有没有更好的解决方案,使我的代码不依赖于输出接口的编码?
在Python中,当我们尝试打印包含非ASCII字符的字符串时,有时会遇到"UnicodeEncodeError: 'charmap' codec can't encode - character maps to
解决这个问题的方法是将要打印的字符串转换为合适的字符编码。这可以通过使用字符串的encode方法来实现。在上述问题中,原始代码是:
print("Process lines, file_name command_line %s\n"% command_line)
要解决这个问题,可以将代码修改为:
print("Process lines, file_name command_line %s\n"% command_line.encode('utf-8'))
这里使用了encode('utf-8')方法将字符串command_line转换为UTF-8编码。
通过这种方式,我们可以确保要打印的字符串能够正确地转换为所选字符编码,从而避免"UnicodeEncodeError"错误的发生。
以上解决方法来源于以下链接:http://blog.notdot.net/2010/07/Getting-unicode-right-in-Python 。
UnicodeEncodeError: 'charmap' codec can't encode - character maps to
为了解决这个问题,可以使用上述提供的代码中的uprint函数来替代print函数。uprint函数会检查输出流的编码,如果是UTF-8编码,则直接使用print函数进行输出。如果不是UTF-8编码,则会将字符串编码为指定的编码格式,然后再解码为相同的编码格式,以此来避免出现编码错误。这样可以确保输出的字符串能够被正确地编码和显示。
需要注意的是,如果输出流不支持某些特定字符,uprint函数会以Unicode编码的形式输出该字符的代码点(如\uXXXX)。如果需要,可以根据自己的需求将'backslashreplace'替换为其他的编码偏好。
总之,使用uprint函数可以解决因输出字符串包含无法编码的字符而导致的UnicodeEncodeError错误。只需将print函数替换为uprint函数,即可在不同的输出流中正确输出包含特殊字符的字符串。
UnicodeEncodeError: 'charmap' codec can't encode - character maps to
1. 改变输出编码,使其始终输出UTF-8。可以参考Setting the correct encoding when piping stdout in Python中的方法,但是可能无法正常工作。
2. 使用下面的示例代码,使输出能够识别目标字符集:
# -*- coding: utf-8 -*- import sys print sys.stdout.encoding print u"Stöcker".encode(sys.stdout.encoding, errors='replace') print u"Стоескер".encode(sys.stdout.encoding, errors='replace')
这个示例会将我的名字中的任何不可打印字符替换为问号。如果创建一个自定义的print函数,使用这种机制来正确编码输出,就可以在需要的地方简单地将print替换为myprint,而不会让整个代码看起来很丑陋。
3. 在软件开始时全局重置输出编码:
在Python 2中:
if sys.stdout.encoding != 'cp850': sys.stdout = codecs.getwriter('cp850')(sys.stdout, 'strict') if sys.stderr.encoding != 'cp850': sys.stderr = codecs.getwriter('cp850')(sys.stderr, 'strict')
在Python 3中:
if sys.stdout.encoding != 'cp850': sys.stdout = codecs.getwriter('cp850')(sys.stdout.buffer, 'strict') if sys.stderr.encoding != 'cp850': sys.stderr = codecs.getwriter('cp850')(sys.stderr.buffer, 'strict')
如果在CGI中输出HTML,可以将'strict'替换为'xmlcharrefreplace'以获取非可打印字符的HTML编码标签。可以根据需要修改这些方法,设置不同的编码。需要注意的是,仍然无法输出非指定的数据。因此,任何数据、输入、文本必须正确转换为Unicode。
这个问题可能会在Windows上出现,但在Linux上测试时并没有出现。