首页 文章

Python 3:如何指定stdin编码

提问于
浏览
24

在将代码从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帖子建议使用

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

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

1 回答

  • 46

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

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

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

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

    或者,在运行python时将PYTHONIOENCODING environment variable设置为所需的编解码器 .

    从Python 3.7开始,您也可以reconfigure the existing std* wrappers,只要您在开始时(在读取任何数据之前)执行此操作:

    # Python 3.7 and newer
    sys.stdin.reconfigure(encoding='utf-8')
    

相关问题