查看: 2111|回复: 3

UnicodeEncodeError: 'charmap' codec can't encode character '\u2014' in positi...

[复制链接]

4

主题

33

帖子

88

积分

注册会员

Rank: 2

积分
88
发表于 2018-9-20 15:52:51 | 显示全部楼层 |阅读模式
我正在编写一个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字符(em-dash),打印功能在Windows GUI中很好地转换,但在Windows控制台中没有。鉴于strict默认行为,我收到以下错误:
UnicodeEncodeError: 'charmap' codec can't encode character '\u2014' in position 10248: character maps to <undefined>
回复

使用道具 举报

9

主题

74

帖子

185

积分

注册会员

Rank: 2

积分
185
发表于 2018-9-20 15:54:49 | 显示全部楼层
我看到三个解决方案:
1.        更改输出编码,因此它将始终输出UTF-8。请参阅例如在Python中管道stdout时设置正确的编码,但我无法让这些示例工作。
2.        以下示例代码使输出可以识别你的目标字符集。
3.        # -*- coding: utf-8 -*-
4.        import sys
5.       
6.        print sys.stdout.encoding
7.        print u"Stöcker".encode(sys.stdout.encoding, errors='replace')
print u"Стоескер".encode(sys.stdout.encoding, errors='replace')
此示例使用问号正确替换了我名称中的任何不可打印字符。
如果你创建一个自定义打印功能,例如调用myprint,使用该机制正确编码输出,你可以简单地用myprint必要的替换打印,而不会使整个代码看起来很丑。
8.        在软件开头全局重置输出编码:
页面http://www.macfreek.nl/memory/Encoding_of_Python_stdout有一个很好的总结如何更改输出编码。特别是“Stdout周围的StreamWriter Wrapper”部分很有意思。基本上它说改变I / O编码函数如下:
在Python 2中:
  1. if sys.stdout.encoding != 'cp850':
  2.   sys.stdout = codecs.getwriter('cp850')(sys.stdout, 'strict')
  3. if sys.stderr.encoding != 'cp850':
  4.   sys.stderr = codecs.getwriter('cp850')(sys.stderr, 'strict')
复制代码

在Python 3中:
  1. if sys.stdout.encoding != 'cp850':
  2.   sys.stdout = codecs.getwriter('cp850')(sys.stdout.buffer, 'strict')
  3. if sys.stderr.encoding != 'cp850':
  4.   sys.stderr = codecs.getwriter('cp850')(sys.stderr.buffer, 'strict')
复制代码

如果在CGI输出HTML中使用,你可以将'strict'替换为'xmlcharrefreplace',以获取不可打印字符的HTML编码标记。
随意修改方法,设置不同的编码,....注意它仍然无法输出非指定的数据。因此,任何数据,输入,文本都必须正确转换为unicode:

  1. # -*- coding: utf-8 -*-
  2. import sys
  3. import codecs
  4. sys.stdout = codecs.getwriter("iso-8859-1")(sys.stdout, 'xmlcharrefreplace')
  5. print u"Stöcker"                # works
  6. print "Stöcker".decode("utf-8") # works
  7. print "Stöcker"                 # fails
复制代码

回复

使用道具 举报

10

主题

82

帖子

200

积分

中级会员

Rank: 3Rank: 3

积分
200
发表于 2018-9-20 15:55:44 | 显示全部楼层
  1. def uprint(*objects, sep=' ', end='\n', file=sys.stdout):
  2.     enc = file.encoding
  3.     if enc == 'UTF-8':
  4.         print(*objects, sep=sep, end=end, file=file)
  5.     else:
  6.         f = lambda obj: str(obj).encode(enc, errors='backslashreplace').decode(enc)
  7.         print(*map(f, objects), sep=sep, end=end, file=file)

  8. uprint('foo')
  9. uprint(u'Antonín Dvořák')
  10. uprint('foo', 'bar', u'Antonín Dvořák')
复制代码
回复

使用道具 举报

11

主题

80

帖子

199

积分

注册会员

Rank: 2

积分
199
发表于 2018-9-20 15:56:31 | 显示全部楼层
出于调试目的,你可以使用print(repr(data))。
要显示文本,请始终打印Unicode。不要硬编码环境的字符编码,例如cp850脚本内部。要解码http respone,请参阅在Python中获取HTTP响应的charset /编码的好方法。
要将Unicode打印到Windows控制台,你可以使用win-unicode-console包。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表