Python 3 TypeError: должен быть str, а не байтами с sys.stdout.write ()

Я искал способ запустить внешний процесс из сценария python и распечатать его сообщения stdout во время выполнения.
Приведенный ниже код работает, но не выводит вывод stdout во время выполнения. Когда он выходит, я получаю следующую ошибку:

sys.stdout.write (nextline) TypeError: должен быть str, а не байтами

p = subprocess.Popen(["demo.exe"],stdout = subprocess.PIPE, stderr= subprocess.PIPE) # Poll process for new output until finished while True: nextline = p.stdout.readline() if nextline == '' and p.poll() != None: break sys.stdout.write(nextline) sys.stdout.flush() output = p.communicate()[0] exitCode = p.returncode 

Я использую python 3.3.2

2 Solutions collect form web for “Python 3 TypeError: должен быть str, а не байтами с sys.stdout.write ()”

Python 3 обрабатывает строки немного иначе. Первоначально для строк был только один тип: str . Когда юникод приобрел тягу в 90-х, новый unicode тип был добавлен для обработки Unicode без нарушения существующего кода 1 . Это фактически то же самое, что и str но с поддержкой многобайтов.

В Python 3 существуют два разных типа:

  • Тип bytes . Это всего лишь последовательность байтов, Python ничего не знает о том, как интерпретировать это как символы.
  • Тип str . Это также последовательность байтов, но Python знает, как интерпретировать эти байты как символы .
  • Отдельный тип unicode был удален. str теперь поддерживает unicode.

В Python 2 неявно предполагается, что кодирование может вызвать множество проблем; вы можете использовать неправильную кодировку, или данные могут вообще не иметь кодировки (например, это изображение PNG).
Явно говорю, что Python, кодирование которого используется (или явно говорящее догадываться), часто намного лучше и намного больше соответствует «философии Python» « явный лучше, чем неявный ».

Это изменение несовместимо с Python 2, поскольку многие возвращаемые значения изменились, что приводит к таким тонким проблемам, как этот; вероятно, это основная причина, по которой принятие Python 3 было настолько медленным. Поскольку у Python нет статического ввода 2, это невозможно автоматически изменить с помощью скрипта (например, в комплекте 2to3 ).

  • Вы можете преобразовать str в bytes с bytes('h€llo', 'utf-8') ; это должно произвести b'H\xe2\x82\xacllo' . Обратите внимание, как один символ был преобразован в три байта.
  • Вы можете преобразовать bytes в str с помощью b'H\xe2\x82\xacllo'.decode('utf-8') .

Конечно, UTF-8 может быть неправильным набором символов в вашем случае, поэтому обязательно используйте правильный.

В вашем конкретном фрагменте кода nextline имеет тип bytes , а не str , чтение stdout и stdin из subprocess измененного в Python 3 от str до bytes . Это связано с тем, что Python не может быть уверен, какую кодировку он использует. Вероятно, он использует то же, что и sys.stdin.encoding (кодирование вашей системы), но это не может быть уверенным.

Вам необходимо заменить:

 sys.stdout.write(nextline) 

с:

 sys.stdout.write(nextline.decode('utf-8')) 

или, может быть:

 sys.stdout.write(nextline.decode(sys.stdout.encoding)) 

Вам также потребуется изменить, if nextline == '' if nextline == b'' поскольку:

 >>> '' == b'' False 

Также см. Python 3 ChangeLog , PEP 358 и PEP 3112 .


1 Есть несколько опрятных трюков, которые вы можете сделать с ASCII, которые вы не можете сделать с многобайтовыми наборами символов; наиболее известным примером является «xor с пространством для переключения случая» (например, chr(ord('a') ^ ord(' ')) == 'A' ) и «установить 6-й бит для создания контрольного символа» (например, ord('\t') + ord('@') == ord('I') ). ASCII был разработан в то время, когда манипулирование отдельными битами – это операция с незначительным воздействием на производительность.

2 Да, вы можете использовать аннотации функций, но это сравнительно новая функция и мало используется.

Хотя принятый ответ будет работать нормально, если байты, которые у вас есть из вашего подпроцесса, кодируются с использованием sys.stdout.encoding (или совместимое кодирование, например чтение из инструмента, который выводит ASCII, а ваш stdout использует UTF-8), правильный способ записать произвольные байты в stdout:

 sys.stdout.buffer.write(some_bytes_object) 

Это будет просто выводить байты как есть, не пытаясь рассматривать их как кодирование в некотором некотором кодировании.

  • Совокупная сумма со списком
  • python .count для многомерных массивов (список списков)
  • Python и Windows: где находится пусковая установка python?
  • Чтение данных из api и заполнение ошибки .csv
  • Список словарей и пиражей
  • Python - нужно перебирать каталоги, ищущие TXT-файлы
  • Доступ к данным API Facebook с помощью Python
  • Как сделать перенаправление и сохранить строку запроса?
  •  
    Interesting Posts for Van-Lav

    Удаление номеров из строки

    Где файлы, загруженные с помощью пипса, хранятся в virtualenv?

    Как измерить время между строками кода в python?

    Написание тела ответа с помощью BaseHTTPRequestHandler

    Создать дескриптор свойства экземпляра?

    Как написать список с плавающей запятой в файл в Python

    Добавление элементов в генераторы питона

    Django-Grappelli: Обратное для 'grp_related_lookup' с аргументами '()' и аргументами ключевого слова '{}' не найдено

    Python – странное поведение с dicts в списке

    Является ли SSE невыровненной нагрузкой внутренней, чем медленная, чем выровненная нагрузка на процессоры Intel x64_64?

    Ошибка синтаксиса, выполняющая код python из базы данных

    Сопряжение значений дочернего элемента и вложенного дочернего элемента из проанализированных XML-файлов

    Запустить скрипт python в контейнере в графическом интерфейсе

    Конфигурационный файл Python: любая рекомендация формата файла? Формат INI по-прежнему подходит? Кажется довольно старой школой

    Разделить строку запятыми, но игнорировать запятые в двойных кавычках?

    Python - лучший язык программирования в мире.