Unicode Zen в Python 2.x — длинная версия
Не видя источника, трудно понять причину, поэтому мне придется говорить в целом.
обычно происходит, когда вы пытаетесь преобразовать Python 2.x , который не является ASCII, в строку Unicode без указания кодировки исходной строки.
Вкратце, строки Unicode — это совершенно отдельный тип строки Python, которая не содержит никакой кодировки. Они содержат только коды точек Unicode и поэтому могут содержать любую точку Unicode по всему спектру. Строки содержат кодированный текст, beit UTF-8, UTF-16, ISO-8895-1, GBK, Big5 и т.д. Строки декодируются в Unicode и Юникоды кодируются в строки . Файлы и текстовые данные всегда передаются в закодированных строках.
Авторы модуля Markdown, вероятно, используют (где выбрасывается исключение) в качестве качественного шлюза для остальной части кода — он преобразует ASCII или переупорядочивает существующие строки Unicodes в новую строку Unicode. Авторы Markdown не могут знать кодировку входящей строки, поэтому будут полагаться на то, что вы декодируете строки в строки Unicode, прежде чем перейти к Markdown.
Строки Unicode могут быть объявлены в вашем коде с помощью префикса к строкам. Например.
Строки Unicode могут также поступать из файлов, баз данных и сетевых модулей. Когда это происходит, вам не нужно беспокоиться о кодировке.
Python 3
Python 3 не более Unicode способен, чем Python 2.x, однако он немного менее запутан в теме. Например, обычное теперь является строкой Unicode, а старое теперь .
По умолчанию используется кодировка UTF-8, поэтому, если вы байтовой строки не указали кодировку, Python 3 использует кодировку UTF-8. Это, вероятно, решает 50% проблем Unicode людей.
Кроме того, по умолчанию работает в текстовом режиме, поэтому возвращает декодированное (Unicode). Кодировка получена из вашей локали, которая имеет тенденцию быть UTF-8 в системах Un * x или 8-битной кодовой страницей, такой как windows-1251, в блоках Windows.
Example
Python 2.x2.7
“1deadbeef3″.decode(‘hex’)# Out: ‘x1dxeaxdbxeexf3”x1dxeaxdbxeexf3’.encode(‘hex’)# Out: 1deadbeef3
Python 3.x3.0
“1deadbeef3”.decode(‘hex’)# Traceback (most recent call last):# File “<stdin>”, line 1, in <module># AttributeError: ‘str’ object has no attribute ‘decode’b”1deadbeef3″.decode(‘hex’)# Traceback (most recent call last):# File “<stdin>”, line 1, in <module># LookupError: ‘hex’ is not a text encoding; use codecs.decode() to handle arbitrary codecs’x1dxeaxdbxeexf3′.encode(‘hex’)# Traceback (most recent call last):# File “<stdin>”, line 1, in <module># LookupError: ‘hex’ is not a text encoding; use codecs.encode() to handle arbitrary codecsb’x1dxeaxdbxeexf3′.encode(‘hex’)# Traceback (most recent call last):# File “<stdin>”, line 1, in <module># AttributeError: ‘bytes’ object has no attribute ‘encode’
However, as suggested by the error message, you can use the codecs module to achieve the same result:
import codecscodecs.decode(‘1deadbeef4’, ‘hex’)# Out: b’x1dxeaxdbxeexf4’codecs.encode(b’x1dxeaxdbxeexf4′, ‘hex’)# Out: b’1deadbeef4′
Note that codecs.encode returns a bytes object. To obtain a str object just decode to ASCII:
codecs.encode(b’x1dxeaxdbxeexff’, ‘hex’).decode(‘ascii’)# Out: ‘1deadbeeff’
Юникод сэндвич
Хорошей практикой является формирование сэндвича Unicode в вашем коде, где вы декодируете все входящие данные в строки Unicode, работаете с Unicodes, а затем кодируете в s на выходе. Это избавляет вас от беспокойства о кодировании строк в середине вашего кода.
Ввод/Декодирование
Исходный код
Если вам нужно добавить не-ASCII в ваш исходный код, просто создайте строки Unicode, добавив префикс . Например.
Чтобы позволить Python декодировать исходный код, вам необходимо добавить заголовок кодирования, соответствующий фактической кодировке вашего файла. Например, если ваш файл был закодирован как UTF-8, вы должны использовать:
Это необходимо только в том случае, если в исходном коде есть код (не = ASCII) .
Обычно не-ASCII данные получаются из файла. Модуль предоставляет TextWrapper, который декодирует ваш файл на лету, используя заданное . Вы должны использовать правильную кодировку для файла — это не может быть легко угадано. Например, для файла UTF-8:
Тогда будет подходящим для перехода к Markdown. Если из строки , то вы, вероятно, использовали неправильное значение кодировки.
Модуль Python 2.7 CSV не поддерживает символы не ASCII ????. Однако помощь под рукой: https://pypi.python.org/pypi/backports.csv .
Используйте его как выше, но передайте ему открытый файл:
Базы данных
Большинство драйверов баз данных Python могут возвращать данные в Unicode, но обычно требуют небольшой настройки. Всегда используйте строки Unicode для запросов SQL.
В строке подключения добавьте:
Например.
Добавлять:
HTTP
Веб-страницы могут быть закодированы практически в любой кодировке. Заголовок должен содержать поле для указания на кодировку. Затем содержимое может быть декодировано вручную в соответствии с этим значением. В качестве альтернативы Python-Requests возвращает Unicodes в .
Вручную
Если вам необходимо декодировать строки вручную, вы можете просто выполнить , где — подходящая кодировка. Python 2.x поддерживаемые кодеки приведены здесь: . Опять же, если вы получите , значит, вы, вероятно, ошиблись кодировкой.
Результат
стандартный вывод/печать
пишет через поток stdout. Python пытается настроить кодировщик на стандартный вывод, чтобы Unicodes кодировались в кодировку консоли. Например, если оболочки Linux — , выходные данные будут закодированы в . В Windows вы будете ограничены 8-битной кодовой страницей.
Неправильно настроенная консоль, например поврежденная локаль, может привести к неожиданным ошибкам печати. Переменная окружения может форсировать кодирование для stdout.
5 ответов
начните с Python 3, вся строка является объектом unicode.
a = ‘Happy New Year’ # Python 3 b = unicode(‘Happy New Year’) # Python 2
код перед тем же. Поэтому я думаю, что вы должны удалить .decode(‘utf-8’). Потому что вы уже получили объект unicode.
используйте его этим методом:
str.encode().decode()
Я не знаком с библиотекой, но если ваша проблема в том, что вам не нужен массив байтов, один простой способ-указать тип кодировки прямо в приведении:
>>> my_byte_strb’Hello World’>>> str(my_byte_str, ‘utf-8′)’Hello World’
Он уже декодирован в Python3, попробуйте напрямую, он должен работать.
Gotchas
Преобразование из в Unicode может происходить, даже если вы явно не вызываете .
Следующие сценарии вызывают исключения :
Примеры
На следующей диаграмме вы можете видеть, как Word был закодирован в кодировке UTF-8 или Cp1252 в зависимости от типа терминала. В обоих примерах — это просто обычная ascii. В UTF-8 код кодируется двумя байтами. В «Cp1252» é равно 0xE9 (что также является значением точки Unicode (это не совпадение)). Правильная вызывается, и преобразование в Python Юникод прошло успешно:
На этой диаграмме вызывается с (что аналогично вызову без заданной кодировки). Поскольку ASCII не может содержать байтов больше , это вызовет исключение :
Модель представления текста
Главное различие между Python 2 и Python 3 –базовые типы, существующие для работы со строками и байтовыми строками. В Python 3 мы имеем один строковый тип:
str
, который хранит данные в Unicode, и два байтовых типа:
bytes
и
bytearray
С другой стороны, в Python 2 у нас есть два строковых типа:
str
, который достаточен для любых целей и задач, ограниченных строками в кодировке ASCII + некоторыми неопределенными данными, превышающими интервал в 7 бит. Вместе с типом str у Python2 есть тип данных
unicode
, эквивалентный типу данных
str
Python 3. Для работы с байтами в Python 2 есть один тип:bytearray, взятый из Python 3. Присмотревшись к ситуации, вы можете заметить, что из Python 3 кое-что удалили: поддержку строковых данных не в юникоде.Компенсацией жертвоприношения стал хешируемый байтовый тип данных(
bytes
). Тип данных
bytarray
изменяемый, а поэтому он не может быть хеширован. Я очень редко, использую бинарные данные как ключи словаря, а потому возможность или невозможность хеширования бинарных данных не кажется мне очень серьезной. Особенно в Python 2, так как байты могут быть без каких-либо проблем помещены в переменную типа
str