42

在将代码从 Python 2 移植到 Python 3 时,我在从标准输入读取 UTF-8 文本时遇到了这个问题。在 Python 2 中,这很好用:

for line in sys.stdin:
    ...

但是 Python 3 需要来自sys.stdin的 ASCII ,如果输入中有非 ASCII 字符,我会收到错误消息:

UnicodeDecodeError:'ascii'编解码器无法解码字节..在位置..:序数不在范围内(128)

对于常规文件,我会在打开文件时指定编码:

with open('filename', 'r', encoding='utf-8') as file:
    for line in file:
        ...

但是如何指定标准输入的编码呢?其他 SO 帖子(例如How to change the stdin encoding on python)建议使用

input_stream = codecs.getreader('utf-8')(sys.stdin)
for line in input_stream:
    ...

但是,这在 Python 3 中不起作用。我仍然收到相同的错误消息。我使用的是 Ubuntu 12.04.2,我的语言环境设置为 en_US.UTF-8。

4

1 回答 1

89

Python 3期望sys.stdin. 它将stdin以文本模式打开,并对使用的编码做出有根据的猜测。这个猜测可能会归结为ASCII,但这不是给定的。请参阅有关如何选择编解码器的sys.stdin文档。

与其他以文本模式打开的文件对象一样,该sys.stdin对象派生自io.TextIOBase基类;它有一个.buffer指向底层缓冲 IO 实例的属性(它又具有一个.raw属性)。

将属性包装sys.stdin.buffer在新io.TextIOWrapper()实例中以指定不同的编码:

import io
import sys

input_stream = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8')

或者,在运行 python 时将PYTHONIOENCODING环境变量设置为所需的编解码器。

从 Python 3.7 开始,您还可以重新配置现有的std*wrappers,前提是您在一开始就这样做(在读取任何数据之前):

# Python 3.7 and newer
sys.stdin.reconfigure(encoding='utf-8')
于 2013-05-14T17:33:34.723 回答