如何在 Python 3 中设置 sys.stdout 编码?
- 2024-12-30 08:41:00
- admin 原创
- 53
问题描述:
在 Python 2 中设置默认输出编码是一个众所周知的习惯用法:
sys.stdout = codecs.getwriter("utf-8")(sys.stdout)
这将sys.stdout
对象包装在以 UTF-8 编码输出的编解码器编写器中。
然而,这种技术在 Python 3 中不起作用,因为它sys.stdout.write()
期望的是str
,但编码的结果却是,因此在尝试将编码后的字节写入原始bytes
时会发生错误。codecs
`sys.stdout`
在 Python 3 中执行此操作的正确方法是什么?
解决方案 1:
从 Python 3.7 开始,你可以使用以下命令更改标准流的编码reconfigure()
:
sys.stdout.reconfigure(encoding='utf-8')
您还可以通过添加参数来修改处理编码错误的方式errors
。
解决方案 2:
Python 3.1 添加了io.TextIOBase.detach()
,并在文档中添加了一条注释sys.stdout
:
标准流默认为文本模式。要向这些流写入或读取二进制数据,请使用底层二进制缓冲区。例如,要将字节写入
stdout
,请使用sys.stdout.buffer.write(b'abc')
。io.TextIOBase.detach()
默认情况下,使用流可以设为二进制。此函数将stdin
和stdout
设为二进制:def make_streams_binary(): sys.stdin = sys.stdin.detach() sys.stdout = sys.stdout.detach()
因此,Python 3.1 及更高版本对应的习语是:
sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())
解决方案 3:
我在寻找相同错误的解决方案时发现了这个线程,
对于我来说,除了已经建议的解决方案之外,还有一个替代解决方案,即在Python 启动之前设置PYTHONIOENCODING
环境变量- 这比在 Python 初始化之后进行交换麻烦更少:sys.stdout
PYTHONIOENCODING=utf-8:surrogateescape python3 somescript.py
其优点是不需要去编辑 Python 代码。
解决方案 4:
其他答案似乎建议使用codecs
,但open
对我有用:
import sys
sys.stdout = open(sys.stdout.fileno(), mode='w', encoding='utf8', buffering=1)
print("日本語")
# Also works with other methods of writing to stdout:
sys.stdout.write("日本語
")
sys.stdout.buffer.write("日本語
".encode())
即使我用 运行它,它也有效PYTHONIOENCODING="ascii"
。
解决方案 5:
在 Python 2 中设置默认输出编码是一个众所周知的习惯用法
哎呀!这是 Python 2 中一个众所周知的习惯用法吗?在我看来,这是一个危险的错误。
它肯定会弄乱任何试图将二进制写入 stdout 的脚本(例如,如果您是返回图像的 CGI 脚本,则需要它)。字节和字符是完全不同的事物;用仅接受字符的接口来修补指定接受字节的接口并不是一个好主意。
CGI 和 HTTP 通常明确使用字节。您只应将字节发送到 sys.stdout。在 Python 3 中,这意味着使用sys.stdout.buffer.write
直接发送字节。对页面内容进行编码以匹配其charset
参数应该在应用程序中的更高级别进行处理(在您返回文本内容而不是二进制内容的情况下)。这也意味着print
它不再适用于 CGI。
(更令人困惑的是,wsgiref 的 CGIHandler 直到最近才在 py3k 中被破坏,因此无法通过这种方式将 WSGI 部署到 CGI。借助 PEP 3333 和 Python 3.2,这终于可以实现。)
解决方案 6:
使用detach()
会导致解释器在退出之前尝试关闭标准输出时打印警告:
Exception ignored in: <_io.TextIOWrapper mode='w' encoding='UTF-8'>
ValueError: underlying buffer has been detached
相反,这对我来说很有效:
default_out = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
(当然,写入default_out
而不是标准输出。)
解决方案 7:
sys.stdout
在 Python 3 中处于文本模式。因此您可以直接向其写入 unicode,而不再需要 Python 2 的习语。
在 Python 2 中,以下代码会失败:
>>> import sys
>>> sys.stdout.write(u"ûnicöde")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'xfb' in position 0: ordinal not in range(128)
然而,它在 Python 3 中运行得很好:
>>> import sys
>>> sys.stdout.write("Ûnicöde")
Ûnicöde7
现在,如果您的 Python 不知道您的 stdouts 编码实际上是什么,那就是另一个问题,很可能是在 Python 的构建中。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理必备:盘点2024年13款好用的项目管理软件