0

Python UnicodeDecodeError - Неправильно ли я понимаю кодировку?

13

Проблема с кодировкой в Python

У меня возникла проблема с кодировкой строки в Python. Я пытался добавить строку 'add \x93Monitoring\x93 to list' в список, используя метод encode с параметром 'latin-1' и ignore, но это приводит к ошибке. Я ожидал, что параметр 'ignore' должен был помочь игнорировать недопустимые символы. Вот код, который вызывает ошибку:

>>> 'add \x93Monitoring\x93 to list '.encode('latin-1','ignore')

В результате выполнения этого кода появляется следующая ошибка:

Traceback (most recent call last):
  File "<interactive input>", line 1, in ?
UnicodeDecodeError: 'ascii' codec can't decode byte 0x93 in position 4: ordinal not in range(128)

Не могли бы вы подсказать, почему это происходит и как правильно обработать данную ситуацию?

2 ответ(ов)

2

Здесь есть причина, по которой их называют "кодировками"...

Немного вводной информации: думайте о юникоде как о норме или идеальном состоянии. Юникод — это просто таблица символов. №65 — это латинская заглавная буква A. №937 — греческая заглавная омега. И только это.

Чтобы компьютер мог хранить и/или обрабатывать юникод, он должен закодировать его в байты. Самая простая кодировка юникода — UCS-4; каждый символ занимает 4 байта, и доступны все ~1000000 символов. Эти 4 байта содержат номер символа в таблицах юникода как 4-байтовое целое число. Еще одна очень полезная кодировка — UTF-8, которая может кодировать любой символ юникода с помощью одного до четырех байтов. Но также есть и некоторые ограниченные кодировки, такие как "latin1", которые включают очень ограниченный диапазон символов, в основном используемых западными странами. Такие кодировки используют всего один байт на символ.

По сути, юникод может быть закодирован с помощью множества кодировок, и закодированные строки могут быть декодированы обратно в юникод. Дело в том, что юникод появился довольно поздно, так что все мы, кто вырос на 8-битных символьных наборах, узнали слишком поздно, что всё это время мы работали с закодированными строками. Кодировка могла быть ISO8859-1, или windows CP437, или CP850 и т.д., в зависимости от вашей системной кодовой страницы по умолчанию.

Таким образом, когда в вашем исходном коде вы вводите строку "add “Monitoring“ to list" (и, думаю, вы имели в виду строку "add “Monitoring” to list", обратите внимание на вторую кавычку), вы на самом деле используете строку, уже закодированную в соответствии с кодовой страницей по умолчанию вашей системы (по байту \x93 я предполагаю, что вы используете кодировку Windows 1252 — “Западная”). Если вы хотите получить юникод из этого, вам нужно декодировать строку из кодировки "cp1252".

Таким образом, что вы на самом деле хотели сделать, это:

"add \x93Monitoring\x94 to list".decode("cp1252", "ignore")

К сожалению, в Python 2.x есть и метод .encode для строк; это удобная функция для "специальных" кодировок, таких как "zip", "rot13" или "base64", которые не имеют отношения к юникоду.

В любом случае, все, что вам нужно запомнить для ваших преобразований между юникодом и байтами, это:

  • юникодная строка кодируется в строку Python 2.x (на самом деле — в последовательность байтов)
  • строка Python 2.x декодируется в юникодную строку

В обоих случаях вам необходимо указать кодировку, которая будет использоваться.

Я не очень ясен, я устал, но надеюсь, что смог помочь.

P.S. Юмористическая на заметка: у маяков не было юникода; у древних римлян, древних греков и древних египтян тоже не было. У всех этих цивилизаций были свои "кодировки", и они довольно пренебрегали другими культурами. Все эти цивилизации развалились в прах. Подумайте об этом, люди! Сделайте свои приложения осведомленными о юникоде, ради блага человечества. 😃

P.S.2 Пожалуйста, не портьте предыдущий пост, говоря "Но китайцы...". Если вам нужно это сделать или вы чувствуете, что обязаны, отложите это, подумав, что базовая многобайтовая кодировка Unicode (BMP) в основном состоит из китайских иероглифов, следовательно, китайский является основой юникода. Я могу продолжать выдумывать абсурдные лжи, лишь бы люди разрабатывали приложения, учитывающие юникод.

0

В вашем примере строка, которую вы используете, действительно является строкой Unicode, так как она начинается с u'...'. Это означает, что функция encode доступна для этой строки. Однако, символы, которые вы используете (например, \x93), могут не поддерживаться в вашей текущей кодировке.

Попробуйте использовать метод encode с кодировкой latin-1, чтобы увидеть, как это работает. В вашем коде вы правильно указали ignore, что позволяет игнорировать неподдерживаемые символы.

Вот ваш пример:

>>> u'add \x93Monitoring\x93 to list '.encode('latin-1', 'ignore')
'add \x93Monitoring\x93 to list '

Обратите внимание, что \x93 — это обозначение символа, который может быть не поддержан в кодировке latin-1. Если вы хотите, чтобы он был корректно закодирован, убедитесь, что используете правильную кодировку, например, utf-8, когда это возможно.

Если у вас есть дополнительные вопросы или нужна помощь с кодировкой, дайте знать!

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь