UnicodeEncodeError:'charmap'编解码器无法编码-字符映射到<undefined>,打印函数[重复]

2024-12-18 08:39:00
admin
原创
133
摘要:问题描述:我正在编写一个 Python 3.3 程序,使用 POST 方法将一些数据发送到网页。主要是为了调试过程,我获取页面结果并使用print()函数将其显示在屏幕上。代码如下:conn.request("POST", resource, params, headers) respon...

问题描述:

我正在编写一个 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()方法返回一个对bytes页面进行编码的元素(这是一个格式良好的 UTF-8 文档)。在我停止使用 Windows 版 IDLE GUI 并改用 Windows 控制台之前,它似乎没问题。返回的页面有一个 U+2014 字符(长破折号),打印函数可以在 Windows GUI(我假设代码页 1252)中很好地转换它,但在 Windows 控制台(代码页 850)中却不能。鉴于strict默认行为,我收到以下错误:

UnicodeEncodeError: 'charmap' codec can't encode character '/u2014' in position 10248: character maps to <undefined>

我可以使用这个相当丑陋的代码来修复它:

print(data.decode('utf-8').encode('cp850','replace').decode('cp850'))

现在它用 替换了有问题的字符“—” ?。这不是理想的情况(连字符应该是更好的替代品),但对我的目的来说已经足够了。

我的解决方案中有几点我不太喜欢。

  1. 经过解码、编码、解码之后,代码变得非常丑陋。

  2. 它解决了这种情况的问题。如果我将程序移植到使用其他编码(latin-1、cp437、返回 cp1252 等)的系统,它应该能够识别目标编码。但事实并非如此。(例如,当再次使用 IDLE GUI 时,emdash 也会丢失,这以前没有发生过)

  3. 如果将破折号翻译成连字符而不是疑问号,那就更好了。

问题不在于 emdash(我能想到几种方法来解决这个特定问题),但我需要编写可靠的代码。我向页面提供数据库中的数据,并且该数据可以返回。我可以预见许多其他冲突情况:'Á' U+00c1(在我的数据库中是可能的)可以转换为 CP-850(西欧语言的 DOS/Windows 控制台编码),但不能转换为 CP-437(美国英语的编码,这是许多 Windows 安装中的默认编码)。

是否有更好的解决方案可以使我的代码不受输出接口编码的影响?


解决方案 1:

我发现有三个解决方案:

  1. 更改输出编码,使其始终输出 UTF-8。请参阅在 Python 中管道 stdout 时设置正确的编码,但我无法使这些示例正常工作。

  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')

此示例正确地将我的名字中的任何不可打印字符替换为问号。

如果您创建自定义打印函数,例如调用myprint,使用该机制正确编码输出,您可以简单地在myprint必要的地方用 替换打印,而不会使整个代码看起来很丑陋。

  1. 在软件开始时全局重置输出编码:

页面http://www.macfreek.nl/memory/Encoding_of_Python_stdout很好地总结了如何更改输出编码。特别是“StreamWriter Wrapper around Stdout”部分很有趣。本质上它说要像这样更改 I/O 编码函数:

在 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 中使用,您可以用“xmlcharrefreplace”替换“strict”以获取不可打印字符的 HTML 编码标签。

随意修改方法,设置不同的编码,...请注意,它仍然无法输出未指定的数据。因此,任何数据、输入、文本都必须正确转换为 unicode:

# -*- coding: utf-8 -*-
import sys
import codecs
sys.stdout = codecs.getwriter("iso-8859-1")(sys.stdout, 'xmlcharrefreplace')
print u"Stöcker"                # works
print "Stöcker".decode("utf-8") # works
print "Stöcker"                 # fails

解决方案 2:

根据 Dirk Stöcker 的回答,这里有一个简洁的 Python 3 打印函数包装函数。使用它就像使用打印一样。

另外一个好处是,与其他答案相比,由于最后的解码步骤,这不会将您的文本打印为字节数组(“b“content””),而是打印为普通字符串(“content”)。

def uprint(*objects, sep=' ', end='
', file=sys.stdout):
    enc = file.encoding
    if enc == 'UTF-8':
        print(*objects, sep=sep, end=end, file=file)
    else:
        f = lambda obj: str(obj).encode(enc, errors='backslashreplace').decode(enc)
        print(*map(f, objects), sep=sep, end=end, file=file)

uprint('foo')
uprint(u'Antonín Dvořák')
uprint('foo', 'bar', u'Antonín Dvořák')

解决方案 3:

我对此进行了深入研究,发现最好的解决方案就在这里。

http://blog.notdot.net/2010/07/Getting-unicode-right-in-Python

就我而言,我解决了“UnicodeEncodeError:'charmap'编解码器无法编码字符”

原始代码:

print("Process lines, file_name command_line %s
"% command_line))

新代码:

print("Process lines, file_name command_line %s
"% command_line.encode('utf-8'))  

解决方案 4:

为了调试目的,您可以使用print(repr(data))

要显示文本,请始终打印 Unicode。不要在脚本中对环境的字符编码(例如Cp850)进行硬编码。要解码 HTTP 响应,请参阅在 Python 中获取 HTTP 响应的字符集/编码的好方法。

要将 Unicode 打印到 Windows 控制台,您可以使用win-unicode-console包。

解决方案 5:

如果您使用 Windows 命令行打印数据,则应使用

chcp 65001

这对我有用!

解决方案 6:

如果您使用 Python 3.6(可能是 3.5 或更高版本),它不会再给我这个错误。我遇到了类似的问题,因为我使用的是 v3.4,但在我卸载并重新安装后它就消失了。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用