如何在Python 3中设置sys.stdout编码?

ih99xse1  于 2023-04-13  发布在  Python
关注(0)|答案(7)|浏览(181)

在Python 2中设置默认输出编码是一个众所周知的习惯用法:

sys.stdout = codecs.getwriter("utf-8")(sys.stdout)

这会将sys.stdout对象 Package 在编解码器编写器中,该编解码器编写器以UTF-8编码输出。
然而,这种技术在Python 3中不起作用,因为sys.stdout.write()期望的是str,但编码的结果是bytes,当codecs试图将编码的字节写入原始sys.stdout时,会发生错误。
在Python 3中,正确的方法是什么?

gkn4icbw

gkn4icbw1#

从Python 3.7开始,你可以用reconfigure()改变标准流的编码:

sys.stdout.reconfigure(encoding='utf-8')

您还可以通过添加errors参数来修改编码错误的处理方式。

z5btuh9x

z5btuh9x2#

Python 3.1添加了io.TextIOBase.detach(),在sys.stdout的文档中有一个注解:
默认情况下,标准流处于文本模式。要向这些流写入或读取二进制数据,请使用底层二进制缓冲区。例如,要向stdout写入字节,请使用sys.stdout.buffer.write(b'abc')。使用io.TextIOBase.detach()流可以默认为二进制。此函数将stdinstdout设置为二进制:

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())
0mkxixxg

0mkxixxg3#

我在寻找解决相同错误的方法时发现了这个线程,
对于那些已经建议的解决方案,一个替代方案是在Python启动**之前设置PYTHONIOENCODING环境变量,供我使用-这比在Python初始化后交换sys.stdout麻烦更少:

PYTHONIOENCODING=utf-8:surrogateescape python3 somescript.py

它的优点是不必去编辑Python代码。

6vl6ewon

6vl6ewon4#

其他答案似乎建议使用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("日本語\n")
sys.stdout.buffer.write("日本語\n".encode())

即使我用PYTHONIOENCODING="ascii"运行它,也能正常工作。

u3r8eeie

u3r8eeie5#

在Python 2中设置默认输出编码是一个众所周知的习惯用法
咦!这是Python 2中的一个众所周知的习惯用法吗?在我看来这是一个危险的错误。
它肯定会搞乱任何试图将二进制文件写入标准输出的脚本(例如,如果您是一个返回图像的CGI脚本,您将需要它)。将指定接受字节的接口与只接受字符的接口进行“修补”并不是一个好主意。
CGI和HTTP通常显式地使用字节。您应该只向sys. stdout发送字节。在Python 3中,这意味着使用sys.stdout.buffer.write直接发送字节。编码页面内容以匹配其charset参数应该在应用程序的更高级别处理(在返回文本内容而不是二进制内容的情况下)。这也意味着print不再适合CGI。
(To更令人困惑的是,直到最近,wsgiref的CGIHandler在py 3 k中被破坏了,使得不可能以这种方式将WSGI部署到CGI。

ijnw1ujt

ijnw1ujt6#

使用detach()会导致解释器在退出之前试图关闭stdout时打印一个警告:

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')

(And当然,写入default_out而不是stdout。)

igsr9ssn

igsr9ssn7#

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的构建中。

相关问题