Python-UnicodeEncodeError:“charmap”编解码器无法编码-字符映射到,打印函数

发布于 2021-02-02 23:19:59

我正在编写一个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()方法返回一个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安装中的默认设置)。

所以,问题是:

有没有更好的解决方案,使我的代码与输出接口编码无关?

关注者
0
被浏览
103
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    我看到了三种解决方案:

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

    以下示例代码使输出知道你的目标字符集。

    # -*- 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必要时替换为print即可,而不会使整个代码看起来难看。

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

    http://www.macfreek.nl/memory/Encoding_of_Python_stdout页面上有很好的摘要,说明如何更改输出编码。特别是“围绕Stdout的StreamWriter包装器”这一节很有趣。从本质上讲,它说要更改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中使用,则可以将’​​strict’替换为’xmlcharrefreplace’,以获取不可打印字符的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
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看