Python 3: Как указать кодировку стандартного ввода [дубликата]

На этот вопрос уже есть ответ здесь:

Как изменить кодировку STDIN на Python 4 ответа

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

for line in sys.stdin:
    ...

Но Python 3 ожидает ASCII отsys.stdin, и если на входе есть символы не ASCII, я получаю ошибку:

UnicodeDecodeError: 'ASCII» кодек можетt декодировать байт .. в позиции ..: порядковый номер не в диапазоне (128)

Для обычного файла я бы указал кодировку при открытии файла:

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

Но как я могу указать кодировку для стандартного ввода? Другие SO сообщения (например,Как изменить кодировку STDIN на Python) предложили использовать

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

Тем не менее, это неt работает в Python 3. Я все еще получаю то же сообщение об ошибке. Я'м, используя Ubuntu 12.04.2, и моя локаль установлена на en_US.UTF-8.

Ответы на вопрос(1)

Решение Вопроса

не ожидать 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.

Начиная с Python 3.7, вы также можетеперенастроить существующийstd* обертокпри условии, что вы делаете это в начале (до того, как какие-либо данные будут прочитаны):

# Python 3.7 and newer
sys.stdin.reconfigure(encoding='utf-8')
 CMCDragonkai26 июн. 2018 г., 04:07
Чтобытолько изменить кодировку, нужно сохранить остальные параметры потока:io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8', errors=sys.stdin.errors, newline=sys.stdin.newlines, line_buffering=sys.stdin.line_buffering) Однако я не имеют нашел способ приобрестиwrite_through параметр.
 alvas22 нояб. 2017 г., 02:35
Есть ли способ использоватьsys.stdin.buffer в Python2 тоже?
 Martijn Pieters27 июн. 2016 г., 11:54
 David Epstein03 янв. 2019 г., 11:42
@Martijn Peters: Что происходит по вашим предложениям, если, скажем, один из 1000 байтов был каким-то образом поврежден и вызывает локальное отклонение от utf-8?
 bukzor17 дек. 2013 г., 02:53
@MartijnPieters: это прекрасно работает! Спасибо! Весь сценарий:paste.pound-python.org/show/xoUPpsfFhtKssXBzLxBd  Удаление моих предыдущих неудач.
 Martijn Pieters03 янв. 2019 г., 11:46
@DavidEpstein: этоЭто довольно гипотетическая ситуация. Обработчик ошибок по умолчаниюstrict, поэтому будет возникать исключительная ситуация при попытке прочитать данные из стандартного ввода, которые не соответствуют UTF-8. Установитьerrors возможность другого обработчика ошибок, чтобы изменить это поведение, но поврежденные данные поврежденные данные.
 Martijn Pieters26 июн. 2018 г., 15:39
@CMCDragonkai: Python 3.7 добавляетwrite_through атрибути, что более важно, позволяет вамперенастроить оболочку
 David Epstein03 янв. 2019 г., 13:28
@Martin Pieters В статьях о utf-8 отмечается, что преимущество utf-8 над многими другими кодировками заключается в том, что его легко восстановить после редкой ошибки в потоке байтов. То, что вы говорите, звучит очень полезно в некоторых обстоятельствах (в зависимости от источника ввода).
 Martijn Pieters03 янв. 2019 г., 13:43
@DavidEpstein: да, иустановка обработчика ошибок, кромеstrict позволит вам пропускать поврежденные байты, пока не будет найден новый действительный стартовый байт для последовательности. Ни один из которых не имеет ничего общего с этим конкретным ответом, который универсально применим к Python 'обработка кодировки.
 Irshad Bhat27 июн. 2016 г., 02:25
Если я используюio.TextIOWrapper(sys.stdin.buffer, encoding='utf-8') читать сstdin в питоне 2.7 это syasAttributeError: 'file' object has no attribute 'buffer', Как можно сделать чтение изstdin совместим с Python 2 и 3.
 alvas22 нояб. 2017 г., 09:12
я читаю текст, но хотел бы, чтобы код поддерживал Python2 и Python3, не делая if sys version = (специальноstackoverflow.com/questions/47425695/...
 Martijn Pieters22 нояб. 2017 г., 08:51
@alvas: читать двоичный файл? УвидетьЧтение двоичных данных из stdinI '
 jfs23 мая 2016 г., 20:50
ты можешь позвонитьsys.stdin.detach() вместоsys.stdin.buffer, Хотя предпочтительным решением является оставить исходный код вместе и вместо этого сконфигурировать среду (locale, PYTHONIOENCODING).
 Martijn Pieters16 дек. 2013 г., 22:51
@bukzor: Следующая опция: открыть дескриптор файла напрямую;io.open()0 является :stdinio.open(0) возвращаетTextIOWrapper() объект.
 bukzor12 дек. 2013 г., 23:08
Какие's ближайший эквивалент для python2.6?

Ваш ответ на вопрос