Чтобы интерпретировать последовательность байтов как текст, вы должны знать
соответствующая кодировка символов:
unicode_text = bytestring.decode(character_encoding)
Пример:
>>> b'\xc2\xb5'.decode('utf-8')
'µ'
Команда
ls
может выдавать вывод, который нельзя интерпретировать как текст. Имена файлов
в Unix может быть любая последовательность байтов, кроме косой черты b'/'
и нуля
b'\0'
>>> open(bytes(range(0x100)).translate(None, b'\0/'), 'w').close()
Попытка декодирования такого супа байта с использованием кодировки utf-8 повышает UnicodeDecodeError
.
Может быть и хуже. Декодирование может произойти сбой молча и может привести к mojibake
если вы используете неправильную несовместимую кодировку:
>>> '—'.encode('utf-8').decode('cp1252')
'—'
Данные повреждены, но ваша программа не знает о сбое
произошло.
В общем, какая кодировка символов не используется в самой последовательности байтов. Вы должны сообщить эту информацию вне группы. Некоторые результаты более вероятны, чем другие, и поэтому существует модуль chardet
, который может угадать кодировку символов. Один скрипт Python может использовать несколько кодировок символов в разных местах.
ls
вывод может быть преобразован в строку Python, используя os.fsdecode()
функция, которая преуспевает даже для uncodable
имена файлов (используется
Обработчик ошибок sys.getfilesystemencoding()
и surrogateescape
включен
Unix):
import os
import subprocess
output = os.fsdecode(subprocess.check_output('ls'))
Чтобы получить исходные байты, вы можете использовать os.fsencode()
.
Если вы передадите universal_newlines=True
параметр, тогда subprocess
использует
locale.getpreferredencoding(False)
для декодирования байтов, например, это может быть
cp1252
в Windows.
Чтобы декодировать поток байтов на лету,
io.TextIOWrapper()
можно использовать: пример .
Различные команды могут использовать разные кодировки символов для своих
например, dir
внутренняя команда (cmd
) может использовать cp437. Расшифровать его
вывод, вы можете передать кодировку явно (Python 3.6 +):
output = subprocess.check_output('dir', shell=True, encoding='cp437')
Имена файлов могут отличаться от os.listdir()
(в которых используется Windows
Unicode API), например, '\xb6'
можно заменить на '\x14'
- Python's
кодек cp437 отображает b'\x14'
для управления символом U + 0014 вместо
U + 00B6 (¶). Чтобы поддержать имена файлов с произвольными символами Unicode, см. Декодирование вывода Poweshell, возможно, содержащего символы Unicode, отличные от ascii, в строку Python