ПРИМЕЧАНИЕ: это было написано для Python 2.x. Не уверен, если применимо к 3.x.
Вы правильно используете str
для необработанных двоичных данных в памяти.
[Если вы используете Python 2.6+, даже лучше использовать bytes
, который в 2.6+ является просто псевдонимом str
, но лучше выражает ваше намерение и поможет, если однажды вы перенесете код на Python 3. ]
Как отмечают другие, запись двоичных данных через кодек выглядит странно. Кодек записи принимает Unicode и выводит байты в файл. Вы пытаетесь сделать это задом наперед, отсюда и наша путаница в ваших намерениях ...
[И ваш диагноз ошибки выглядит правильно: так как кодек ожидает Unicode, Python декодирует ваш str в Unicode с кодировкой системы по умолчанию, которая задыхается.]
Что вы хотите видеть в выходном файле?
Если файл должен содержать двоичные данные как есть :
Тогда вы не должны отправлять его через кодек; ты должен написать это
прямо в файл. Кодек кодирует все и может только
Выдать действительные кодировки Unicode (в вашем случае, действительный UTF-8).
Нет данных, которые вы можете дать, чтобы они излучали произвольно
последовательности байтов!
- Если вам требуется смесь UTF-8 и необработанных двоичных данных, вы
должен открыть файл напрямую, и перемешать записи
some_data
с some_text.encode('utf8')
...
Обратите внимание, что смешивание UTF-8 с необработанными произвольными данными очень
плохой дизайн, потому что с такими файлами очень неудобно иметь дело
с! Инструменты, которые понимают Unicode, будут подавлять двоичный файл
данные, оставляя вас с не удобным способом даже просматривать (не говоря уже о
изменить) файл.
Если вы хотите дружественное представление произвольных байтов в
юникода
Передача data.encode('base64')
кодеку. Base64 выдает только
очистить ascii (буквы, цифры и немного знаков препинания)
может быть четко встроено во что угодно,
двоичные данные, и они достаточно компактны (чуть более 33%
накладные расходы).
P.S. Вы можете заметить, что data.encode('base64')
странно.
.encode()
должен принимать Unicode, но я даю ему
строка ?! Python имеет несколько псевдокодеков, которые преобразуют str-> str
такие как 'base64' и 'zlib'.
.encode()
всегда возвращает str, но вы передадите его в кодек
ожидая Unicode ?! В этом случае он будет содержать только чистый
ASCII, так что это не имеет значения. Вы можете написать явно
data.encode('base64').encode('utf8')
если это заставляет тебя чувствовать
лучше.
Если вам необходимо преобразование 1: 1 из произвольных байтов в юникод :
Передача data.decode('latin1')
в кодек. latin1
карт
байты 0-255 для символов Unicode 0-255, что довольно элегантно.
Кодек, конечно, будет кодировать ваши символы - 128-255
закодированы как 2 или 3 байта в UTF-8 (на удивление, средний
накладные расходы составляют 50%, больше, чем base64!). Это довольно убивает
«элегантность» наличия 1: 1.
Обратите внимание, что символы Юникода 0-255 включают в себя противный
невидимые / управляющие символы (перевод строки, подача, мягкий дефис и т. д.)
что делает ваши двоичные данные раздражающими для просмотра в текстовых редакторах.
Учитывая эти недостатки, Я не рекомендую latin1 , если только
вы точно понимаете, почему вы этого хотите.
Я просто упоминаю это как другое "естественное" кодирование, которое возникает
на ум.