Дополнительно
Преобразование байтов в строку
Я использую этот код для получения стандартного вывода из внешней программы:
>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]
Метод communicate() возвращает массив байтов:
>>> command_stdout
b'total 0\n-rw-rw-r-- 1 thomas thomas 0 Mar 3 07:03 file1\n-rw-rw-r-- 1 thomas thomas 0 Mar 3 07:03 file2\n'
Однако я'хотел бы работать с выводом как с обычной строкой Python. Чтобы я мог распечатать ее следующим образом:
>>> print(command_stdout)
-rw-rw-r-- 1 thomas thomas 0 Mar 3 07:03 file1
-rw-rw-r-- 1 thomas thomas 0 Mar 3 07:03 file2
Я думал, что для этого и предназначен метод binascii.b2a_qp(), но когда я попробовал его, то снова получил тот же массив байтов:
>>> binascii.b2a_qp(command_stdout)
b'total 0\n-rw-rw-r-- 1 thomas thomas 0 Mar 3 07:03 file1\n-rw-rw-r-- 1 thomas thomas 0 Mar 3 07:03 file2\n'
Как мне преобразовать байтовое значение обратно в строку? Я имею в виду, используя "аккумуляторы" вместо того, чтобы делать это вручную. И я'хотел бы, чтобы это было нормально с Python 3.
1923
18
Вам нужно декодировать объект bytes, чтобы получить строку:
Вам нужно декодировать байтовую строку и превратить ее в символьную строку (Unicode).
В Python 2
или
На Python 3
или
Я думаю, что это так легко:
Если вы Don'т знать кодировку, чтобы потом прочитать двоичный ввод в строку в Python 3 и Python 2 совместимым способом, используют древние МС-Дос CP437 кодировка:
Потому что кодировка неизвестна, ожидать не-английские символы переводить в символы
cp437
(английские символы не переводятся, поскольку они совпадают в большинстве однобайтовых кодировках и UTF-8).Декодирование произвольных двоичных входных данных в UTF-8 является небезопасным, потому что вы можете сделать это:
То же самое относится к
Латинская-1
, который был популярен (по умолчанию?) для Python 2. Увидеть недостающие пункты в макет кодовой страницы - это где питон дроссели с печально известнойпорядковый номер не в диапазон
.Обновление 20150604: ходят слухи, что Python 3 имеет
surrogateescape
ошибка стратегии для кодирования в двоичном данных без потери данных и сбои, но для этого нужно преобразование тесты,[двоичный] -> [стр] -> [двоичный]
, чтобы проверить производительность и надежность.Обновление 20170116: спасибо комментарий Nearoo - появилась возможность сократить избежать всех неизвестных байт с backslashreplace` обработчик ошибок. Это работает только для Python 3, так что даже это временное решение, вы все равно получите противоречивые выход из разных версий питона:
См. поддержка Unicode в Python для получения подробных сведений.
Обновление 20170119: я решил реализовать Слэш побега декодирования, который работает как питон&ампер;усилитель; nbsp;2 и Python&ампер;усилитель; nbsp;3. Она должна быть медленнее, чем
cp437
решение, но оно должно производить идентичные результаты на любой версии Python.В Python 3, кодировку по умолчанию в
"в UTF-8"
в, так что вы можете напрямую использовать:что эквивалентно
С другой стороны, в Python 2, используется кодировка по умолчанию в строку кодировки по умолчанию. Таким образом, вы должны использовать:
где кодировка-это кодировка, которую вы хотите.
Примечание: в поддержку доводов сайта был добавлен в Python&ампер;усилитель; nbsp;2.7.
Я думаю, ты действительно хочешь этого:
Ответ Aaron'a был правильным, за исключением того, что вам нужно знать какую кодировку использовать. И я полагаю, что Windows использует 'windows-1252'. Это будет иметь значение, только если у вас есть необычные (не ASCII) символы в вашем контенте, но тогда это будет иметь значение.
Кстати, тот факт, что это имеет значение, является причиной того, что Python перешел на использование двух разных типов для двоичных и текстовых данных: он не может волшебным образом конвертировать между ними, потому что он не знает кодировку, пока вы ему не скажете! Единственный способ узнать это - прочитать документацию Windows (или прочитать ее здесь).
Набор universal_newlines значение true, т. е.
В то время как @Аарон мяэнпяа: дизайн для всех'ы ответ просто работает, пользователь недавно:
Вы можете использовать:
декодировать()
имеет стандартный аргумент:Поскольку этот вопрос на самом деле спрашивает о
подпроцесс
выход, у вас есть более прямой подход, посколькук popen
принимает кодирование ключевое слово (в языке Python 3.6+):Общего ответа для других пользователей - расшифруйте байт в текст:
Без аргумента,
sys файла.getdefaultencoding()
будет использоваться. Если ваши данные неsys файла.getdefaultencoding()
, то вы должны явно указать кодировку врасшифровать
вызов:Интерпретировать последовательность байтов в текст, вы должны знать соответствующие кодировки:
Пример:
команда
ls может производить продукцию, которая может'т быть интерпретированы как текст. Имена файлов в Unix может быть любая последовательность байтов, за исключением Слэш
б'/'и ноль б'\0'
:Пытаясь расшифровать такие байта суп, используя кодировку UTF-8 поднимает
UnicodeDecodeError
.Он может быть хуже. Раскодирование могут молча отказать и произвести mojibake если вы используете неправильную несовместимые кодировки:
Если данные повреждены, но ваша программа по-прежнему не подозревая, что неудача произошло.
В общем, что кодировку использовать не встроен в саму последовательность байтов. Вы должны донести эту инфо-каналу. Некоторые результаты более вероятны, чем другие, и поэтому
chardet
существует модуль, который может думаю кодировку. Один скрипт на Python могут использовать несколько кодировок в разных местах.команды
ls
выход может быть преобразован в строку в Python с использованием ОС [.fsdecode()
функции] (), что удается даже для undecodable имена файлов (он используетСыс.getfilesystemencoding()
иsurrogateescape
обработчик ошибок на В Unix):Чтобы получить исходный байт, вы можете использовать
ОС.fsencode()
.Если вы проходите
universal_newlines=правда
параметраподпроцесс
используетязык.getpreferredencoding(ложные)
для декодирования байтов, например, это может бытьcp1252
в Windows.Чтобы расшифровать байтовый поток на лету,
Ио.TextIOWrapper()
могут быть использованы: пример.Различные команды могут использовать различные кодировки для их выход например, внутренние команды DIR `("ЦМД") может использовать cp437. Чтобы расшифровать его выход, можно пройти кодировку явно (питон 3.6+):
Имена файлов могут отличаться от операционной системы.listdir()
(который использует Windows API для Юникода), например,
'\хв6'можно заменить
'\х14'`—питон'ы cp437 кодек карты б'\х14' контролировать символа U+0014 вместо У+00B6 (¶). Для поддержки файлов с произвольными символами Unicode, см. https://stackoverflow.com/q/33936074/4279Если вы должны получить следующие попытки
декодировать()
:Вы также можете указать тип кодировки прямо в гипсе:
При работе с данными из систем Windows (с\R конца строки\п`), мой ответ
Почему? Попробуйте это с многолинейным Input.txt:
Все окончания строк будет в два раза (до
\р\р\н
), что приводит к дополнительной пустой строки. В Python'ы, текст-прочитать функции обычно нормализовать окончаний строк, так что используем только строки\п
. Если вы получаете двоичных данных из системы Windows, Python не имеют шанс сделать это. Таким образом,будет повторить ваш исходный файл.
Я сделал функцию, чтобы очистить список
Для Python 3, это гораздо безопаснее и обновления подход конвертировать из
байт
встроку
:Выход:
С системы системы-конкретные параметры и функции:
Для записи или чтения двоичных данных из/в стандартные потоки, использование базовых двоичных буфера. Например, чтобы записать байты в файл, используйте представление sys.поток stdout.буфер.напишите(б'азбуке')`.
Если вы хотите сконвертировать байты, а не просто строку, преобразованную в байтах:
Но это не очень эффективно,. Получится 2 МБ картинку в 9 МБ.
Для конкретных случае "запустить команду оболочки и сделать свой вывод как текст, а не байт-то", на Python 3.7, вы должны использовать
подпроцесса.запустить
и передать в тексте=правда(а также
capture_output=правда`, чтобы захватить выходные)текст
называлиuniversal_newlines
, и был изменен (ну, псевдоним) в Python 3.7. Если вы хотите поддержка Python до версии 3.7, пройти в universal_newlines=правдавместо
текст=правда`