【问题标题】:Python 3: How to specify stdin encodingPython 3:如何指定标准输入编码
【发布时间】:2013-05-09 02:20:01
【问题描述】:

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

for line in sys.stdin:
    ...

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

UnicodeDecodeError: 'ascii' codec can't decode byte .. in position ..: ordinal not in range(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。

【问题讨论】:

  • @RaymondHettinger 鉴于 Python 2 和 Python 3 在这里有非常不同的答案,这些不是重复的问题。重复的问题会有相同的答案。

标签: python python-3.x unicode encoding stdin


【解决方案1】:

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

与其他以文本模式打开的文件对象一样,sys.stdin 对象派生自 io.TextIOBase base class;它有一个.buffer 属性指向底层缓冲IO 实例(它又具有一个.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')

【讨论】:

  • python2.6 最接近的等价物是什么?
  • @bukzor:下一个选项:直接用io.open()打开文件描述符; 0stdinio.open(0) 返回一个 TextIOWrapper() 对象。
  • @MartijnPieters:效果非常好!谢谢!整个脚本:paste.pound-python.org/show/xoUPpsfFhtKssXBzLxBd删除我以前的失败。
  • @alvas: 读取二进制文件?见Reading binary data from stdin
  • @Suncatcher:IDLE 是这里的 IDE,并用自定义对象替换了标准的 sys.stdout 对象。该类是 IDLE 内部实现的一部分,而不是标准库类。
猜你喜欢
  • 2012-09-30
  • 2011-02-13
  • 1970-01-01
  • 2018-05-05
  • 2013-03-22
  • 1970-01-01
  • 2013-07-30
  • 1970-01-01
  • 2012-11-04
相关资源
最近更新 更多