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

84 投票
7 回答
73921 浏览
提问于 2025-04-16 08:10

在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中,正确的做法是什么呢?

7 个回答

44

我在寻找解决同样错误的方法时发现了这个讨论。

除了已经提到的解决方案,还有一个替代方法,就是在Python启动之前设置一下 PYTHONIOENCODING 这个环境变量。对我来说,这样做比在Python初始化后再去更换 sys.stdout 要简单得多:

PYTHONIOENCODING=utf-8:surrogateescape python3 somescript.py

这样做的好处是,不用去修改Python的代码。

52

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())
63

从Python 3.7开始,你可以通过reconfigure()这个方法来改变标准流的编码方式:

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

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

撰写回答