Python UnicodeDecodeError - Как правильно читать строки юникода из подпроцесса? - PullRequest
0 голосов
/ 13 ноября 2018

У меня проблемы с подпроцессами в Python, которые возвращают символы Юникода, особенно немецкие символы ü, ä, ö.

Мой скрипт в основном хочет открыть подпроцесс, который возвращает некоторые строки с функцией stdout.read(). Некоторые из этих строк могут содержать символы Юникода, но не всегда известно, где находятся эти символы. Таким образом, вывод должен быть как-то декодирован (или закодирован?), Чтобы правильно отображать строку. Я не могу работать с байтовым объектом.

Следующий код вкратце отображает, что я пытаюсь сделать, но не может декодировать строку, поэтому кодек "UnicodeDecodeError: 'utf-8' не может декодировать байт 0x81 в позиции 12: недопустимый начальный байт" Сообщение об ошибке :

import subprocess

command_array = ['echo', 'string_with_ü_ä_ö']
command = subprocess.Popen(command_array, stdout=subprocess.PIPE, shell=True)

command_output = command.stdout.read()
command_output = command_output.decode()
print(command_output)

Я чувствую, что должно быть какое-то тривиальное решение, которое я нигде не смог найти. Есть ли способ правильно вернуть эти символы Юникода в строке?

Я использую Python 3.6.3, и приведенный выше скрипт работает в Windows. Версия, которая работает и под Linux, будет в равной степени оценена!

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Методом проб и ошибок я обнаружил, что декодирование с cp850 работает и дает ожидаемый результат:

import subprocess

command_array = ['echo', 'string_with_ü_ä_ö']
command = subprocess.Popen(command_array, stdout=subprocess.PIPE, shell=True)

command_output = command.stdout.read()
command_output = command_output.decode('cp850')
print(command_output)

Если вы сохраните приведенный выше код в виде utf8 файла (по умолчанию для python3 независимо от платформы) и запустите его с python3, он напечатает:

string_with_ü_ä_ö

К сожалению, я не знаю, где и почему выбрана именно эта кодировка, поэтому она может не работать с разными настройками, но, по крайней мере, я уверен, что она будет работать с вашей.

0 голосов
/ 13 ноября 2018

С Python> = 3.6 вы хотите subprocess.run() с universal_newlines=True

import subprocess

command_array = ['echo', 'string_with_ü_ä_ö']
result = subprocess.run(command_array,
    stdout=subprocess.PIPE, universal_newlines=True)
print(result.stdout)

В Python 3.7 псевдоним universal_newlines был заменен на text, что лучше объясняет, что на самом деле делает опция.

...