Подтвердить что ты не робот

Python 3: Как указать stdin-кодирование

При переносе кода с Python 2 на Python 3 я сталкиваюсь с этой проблемой при чтении текста UTF-8 со стандартного ввода. В Python 2 это прекрасно работает:

for line in sys.stdin:
    ...

Но Python 3 ожидает ASCII от sys.stdin, и если на входе есть символы, отличные от 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.

4b9b3361

Ответ 1

Python 3 не ожидает ASCII от 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')

В качестве альтернативы установите PYTHONIOENCODING переменную окружения в нужный кодек при запуске python.