如何在Python 3中设置sys.stdout编码?
在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()
,可以让流默认变成二进制模式。这个功能会把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())
63
从Python 3.7开始,你可以通过reconfigure()
这个方法来改变标准流的编码方式:
sys.stdout.reconfigure(encoding='utf-8')
你还可以通过添加一个errors
参数来修改编码错误的处理方式。