我正在编写一个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破折号),打印功能在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'))
现在它用?
替换有问题的字符“-”。不是最理想的情况(连字符应该是更好的替代品),但对我来说已经足够好了。
有几件事我不喜欢从我的解决方案。
问题不在于emdash(我可以想出几种方法来解决这个特别的问题),但我需要编写健壮的代码。我正在向页面提供来自数据库的数据,这些数据可以返回。我可以预见许多其他冲突的情况:“Á”U+00c1(在我的数据库中是可能的)可以翻译成CP-850(西欧语言的DOS/Windows控制台编码),但不能翻译成CP-437(美国英语的编码,在许多Windows安装中是默认的)。
所以,问题是:
有没有更好的解决方案,使我的代码不可知从输出接口编码?
我看到了三种解决方案:
更改输出编码,使其始终输出UTF-8。请参见例如Setting the correct encoding when piping stdout in Python,但我无法使这些示例起作用。
下面的示例代码使输出知道目标字符集。
这个例子用问号正确地替换了我名字中任何不可打印的字符。
如果您创建了一个定制的打印函数,例如
myprint
,使用该机制正确地编码输出,您可以在任何需要的地方用myprint
替换打印,而不必使整个代码看起来很难看。在软件开始时全局重置输出编码:
页面http://www.macfreek.nl/memory/Encoding_of_Python_stdout很好地总结了如何更改输出编码。特别是“StreamWriter包装Stdout”一节很有意思。实际上,它说要像这样更改I/O编码函数:
在Python 2中:
在Python 3中:
如果在CGI输出HTML中使用,则可以用“xmlcharrefreplace”替换“strict”,以获取不可打印字符的HTML编码标记。
请随意修改方法,设置不同的编码。。。。请注意,输出非指定数据仍然不起作用。因此,任何数据、输入、文本都必须能够正确地转换为unicode:
出于调试目的,可以使用
print(repr(data))
。要显示文本,请始终打印Unicode。不要在脚本中硬编码环境的字符编码,例如Cp850。要解码HTTP响应,请参见A good way to get the charset/encoding of an HTTP response in Python。
要将Unicode打印到Windows控制台,可以use ^{} package 。
基于Dirk Stócker的答案,这里有一个用于Python3打印函数的简洁包装函数。使用它就像使用打印一样。
作为额外的好处,与其他答案相比,这不会将文本打印为bytearray('b“content“),而是作为普通字符串('content'),因为最后一个解码步骤。
相关问题 更多 >
编程相关推荐