在 Python 中通过管道传输标准输出时设置正确的编码

新手上路,请多包涵

当通过管道传输 Python 程序的输出时,Python 解释器会对编码感到困惑,并将其设置为 None。这意味着这样的程序:

 # -*- coding: utf-8 -*-
print u"åäö"

正常运行时会正常工作,但会失败:

UnicodeEncodeError: ‘ascii’ 编解码器无法对位置 0 中的字符 u’\xa0’ 进行编码:序号不在范围内 (128)

在管道序列中使用时。

管道时使这项工作最好的方法是什么?我可以告诉它使用 shell/文件系统/正在使用的任何编码吗?

到目前为止,我所看到的建议是直接修改您的 site.py,或使用此 hack 对 defaultencoding 进行硬编码:

 # -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
print u"åäö"

有没有更好的方法使管道工作?

原文由 Joakim Lundborg 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 351
2 个回答

您的代码在脚本中运行时有效,因为 Python 将输出编码为您的终端应用程序使用的任何编码。如果您正在使用管道,则必须自己对其进行编码。

一条经验法则是:始终在内部使用 Unicode。解码您收到的内容,并对您发送的内容进行编码。

 # -*- coding: utf-8 -*-
print u"åäö".encode('utf-8')

另一个教学示例是用于在 ISO-8859-1 和 UTF-8 之间进行转换的 Python 程序,使两者之间的所有内容都大写。

 import sys
for line in sys.stdin:
    # Decode what you receive:
    line = line.decode('iso8859-1')

    # Work with Unicode internally:
    line = line.upper()

    # Encode what you send:
    line = line.encode('utf-8')
    sys.stdout.write(line)

设置系统默认编码不是一个好主意,因为您使用的某些模块和库可能依赖于它是 ASCII 的事实。不要这样做。

原文由 nosklo 发布,翻译遵循 CC BY-SA 3.0 许可协议

首先,关于这个解决方案:

 # -*- coding: utf-8 -*-
print u"åäö".encode('utf-8')

每次都使用给定的编码显式打印是不切实际的。那将是重复的并且容易出错。

更好的解决方案是在程序开始时更改 sys.stdout 以使用选定的编码进行编码。这是我在 Python 上找到的一种解决方案:How is sys.stdout.encoding chosen? ,特别是“toka”的评论:

 import sys
import codecs
sys.stdout = codecs.getwriter('utf8')(sys.stdout)

原文由 Craig McQueen 发布,翻译遵循 CC BY-SA 2.5 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题