python - 如何从 stdin 读取输入并强制执行编码?

标签 python file utf-8 io stdin

目标是持续从 stdin 读取并在 Python2 和 Python3 中强制执行 utf8

我尝试过以下解决方案:

我试过:

#!/usr/bin/env python

from __future__ import print_function, unicode_literals
import io
import sys

# Supports Python2 read from stdin and Python3 read from stdin.buffer
# https://stackoverflow.com/a/23932488/610569
user_input = getattr(sys.stdin, 'buffer', sys.stdin)


# Enforcing utf-8 in Python3
# https://stackoverflow.com/a/16549381/610569
with io.TextIOWrapper(user_input, encoding='utf-8') as fin:
    for line in fin:
        # Reads the input line by line
        # and do something, for e.g. just print line.
        print(line)

代码在 Python3 中有效,但在 Python2 中,TextIOWrapper 没有读取函数,它会抛出:

Traceback (most recent call last):
  File "testfin.py", line 12, in <module>
    with io.TextIOWrapper(user_input, encoding='utf-8') as fin:
AttributeError: 'file' object has no attribute 'readable'

那是因为在 Python 中 user_input ,即 sys.stdin.buffer 是一个 _io.BufferedReader 对象及其属性具有可读:

<class '_io.BufferedReader'>

['__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_checkClosed', '_checkReadable', '_checkSeekable', '_checkWritable', '_dealloc_warn', '_finalizing', 'close', 'closed', 'detach', 'fileno', 'flush', 'isatty', 'mode', 'name', 'peek', 'raw', 'read', 'read1', 'readable', 'readinto', 'readinto1', 'readline', 'readlines', 'seek', 'seekable', 'tell', 'truncate', 'writable', 'write', 'writelines']

而在 Python2 中,user_input 是一个文件对象,它的属性没有 readable:

<type 'file'>

['__class__', '__delattr__', '__doc__', '__enter__', '__exit__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'closed', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 'readline', 'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writelines', 'xreadlines']

最佳答案

如果你不需要一个完整的io.TextIOWrapper,而只是一个用于读取的解码流,你可以使用codecs.getreader()来创建一个解码包装器:

reader = codecs.getreader('utf8')(user_input)
for line in reader:
    # do whatever you need...
    print(line)

codecs.getreader('utf8')codecs.StreamReader 创建工厂,然后使用原始流对其进行实例化。 我不确定 StreamReader 是否支持 with 上下文,但这可能不是绝对必要的(我想在阅读后不需要关闭 STDIN……)。

在底层流只提供非常有限的接口(interface)的情况下,我已经成功地使用了这个解决方案。

更新(第二版)

从评论中可以清楚地看出,您实际上需要一个 io.TextIOWrapper 才能在交互模式下进行适当的行缓冲等; codecs.StreamReader 仅适用于管道输入等。

使用 this answer ,我能够使交互式输入正常工作:

#!/usr/bin/env python
# coding: utf8

from __future__ import print_function, unicode_literals
import io
import sys

user_input = getattr(sys.stdin, 'buffer', sys.stdin)

with io.open(user_input.fileno(), encoding='utf8') as f:
    for line in f:
        # do whatever you need...
        print(line)

这将创建一个 io.TextIOWrapper,并从二进制 STDIN 缓冲区强制编码。

关于python - 如何从 stdin 读取输入并强制执行编码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47425695/

相关文章:

Python MySQLdb上传UnicodeEncodeError

python - Unicode解码错误: ‘utf-8’ codec can’t decode byte 0xbe in position 2: invalid start byte

utf-8 - openssl req utf8 字符串

python - 如何在 debian sid 上安装 Tkinter?

python - 如何在 pandas 中查询 MultiIndex 索引列的值

python - 使用 Python 将 JSON 转换为文本文件

python - 使用 python 或 bash 按时间戳将音频文件复制到新文件夹

c - 读取txt文件中的特定字符串并将该字符串转换为int C

java - 如何在文本文件中的两个日期之间进行搜索??? HashMap ?

c# - 在 C# 中使用带有正则表达式的 Directory.GetFiles?