Подтвердить что ты не робот

Кодирование и декодирование строк?

Вот мои попытки с сообщениями об ошибках. Что я делаю не так?

string.decode("ascii", "ignore")

UnicodeEncodeError: кодек 'ascii' не может кодировать символ u '\ xa0' в позиция 37: порядковый номер вне диапазона (128)

string.encode('utf-8', "ignore")

UnicodeDecodeError: кодек "ascii" не может декодировать байт 0xc2 в позиции 37: порядковый номер вне диапазона (128)

4b9b3361

Ответ 1

Вы не можете декодировать unicode, и вы не можете закодировать str. Попробуйте сделать это в обратном направлении.

Ответ 2

Угадывая все вещи, опущенные из исходного вопроса, но, предполагая, что Python 2.x должен внимательно прочитать сообщения об ошибках: в частности, когда вы вызываете "encode", но в сообщении говорится "декодировать" и наоборот, но также и типы значений, включенных в сообщения.

В первом примере string имеет тип unicode, и вы попытались его декодировать, что является операцией преобразования строки байта в unicode. Python попытался преобразовать значение unicode в str, используя стандартную кодировку ascii, но поскольку ваша строка содержала символ non-ascii, вы получили сообщение об ошибке, в которой говорится, что Python не смог закодировать a unicode. Вот пример, который показывает тип входной строки:

>>> u"\xa0".decode("ascii", "ignore")

Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    u"\xa0".decode("ascii", "ignore")
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 0: ordinal not in range(128)

Во втором случае вы делаете обратную попытку кодирования байтовой строки. Кодирование - это операция, которая преобразует unicode в байтовую строку, поэтому Python помогает сначала преобразовать вашу байтовую строку в unicode, и, поскольку вы не дали ей строку ascii, по умолчанию декодирует ascii-декодер:

>>> "\xc2".encode("ascii", "ignore")

Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    "\xc2".encode("ascii", "ignore")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 0: ordinal not in range(128)

Ответ 3

Помимо получения decode и encode назад, я думаю, что часть ответа здесь на самом деле не использует кодировку ascii. Вероятно, это не то, что вы хотите.

Для начала подумайте о str, как и в текстовом файле. Это всего лишь куча байтов без привязки к ней. То, как оно интерпретируется, зависит от того, какая часть кода читает его. Если вы не знаете, о чем идет речь в этом параграфе, прочитайте Joel Абсолютный минимум Каждый разработчик программного обеспечения Абсолютно, положительно должен знать о Unicode и наборах символов прямо сейчас перед вами идти дальше.

Естественно, мы все знаем о создавшемся беспорядке. Ответ заключается в том, чтобы, по крайней мере, в памяти, иметь стандартную кодировку для всех строк. Это где unicode приходит. У меня возникли проблемы с отслеживанием того, что кодирование Python использует внутренне точно, но на самом деле это не имеет значения только для этого. Дело в том, что вы знаете, что это последовательность байтов, которые интерпретируются определенным образом. Поэтому вам нужно только подумать о самих символах, а не о байтах.

Проблема в том, что на практике вы сталкиваетесь с обоими. Некоторые библиотеки дают вам str, а некоторые ожидают a str. Разумеется, это имеет смысл всякий раз, когда вы передаете последовательность байтов (например, на диск или с помощью веб-запроса или с него). Таким образом, вы должны иметь возможность переводить назад и вперед.

Введите codecs: это библиотека перевода между этими двумя типами данных. Вы используете encode для генерации последовательности байтов (str) из текстовой строки (unicode), и вы используете decode для получения текстовой строки (unicode) из последовательности байтов ().

Например:

>>> s = "I look like a string, but I'm actually a sequence of bytes. \xe2\x9d\xa4"
>>> codecs.decode(s, 'utf-8')
u"I look like a string, but I'm actually a sequence of bytes. \u2764"

Что здесь произошло? Я дал Python последовательность байтов, а затем я сказал: "Дайте мне версию unicode этого, учитывая, что эта последовательность байтов находится в 'utf-8'". Это было так, как я спросил, и эти байты (сердечный персонаж) теперь рассматриваются как целое, представленное их кодовым номером Unicode.

Отпустите другой путь:

>>> u = u"I'm a string! Really! \u2764"
>>> codecs.encode(u, 'utf-8')
"I'm a string! Really! \xe2\x9d\xa4"

Я дал Python строку Unicode, и я попросил ее перевести строку в последовательность байтов, используя кодировку 'utf-8'. Так оно и было, и теперь сердце - это просто куча байтов, который он не может печатать как ASCII; поэтому он показывает мне шестнадцатеричный код.

Мы также можем работать с другими кодировками:

>>> s = "I have a section \xa7"
>>> codecs.decode(s, 'latin1')
u'I have a section \xa7'
>>> codecs.decode(s, 'latin1')[-1] == u'\u00A7'
True

>>> u = u"I have a section \u00a7"
>>> u
u'I have a section \xa7'
>>> codecs.encode(u, 'latin1')
'I have a section \xa7'

('\xa7' является символом , как в Unicode и Latin-1.)

Итак, для вашего вопроса вам сначала нужно выяснить, что такое кодировка вашего str.

  • Это из файла? Из веб-запроса? Из вашей базы данных? Затем источник определяет кодировку. Узнайте кодировку источника и используйте его для перевода в unicode.

    s = [get from external source]
    u = codecs.decode(s, 'utf-8') # Replace utf-8 with the actual input encoding
    
  • Или, может быть, вы пытаетесь его где-то написать. Какую кодировку ожидает цель? Используйте это, чтобы перевести его в str. UTF-8 - хороший выбор для текстовых документов; большинство вещей может прочитать его.

    u = u'My string'
    s = codecs.encode(u, 'utf-8') # Replace utf-8 with the actual output encoding
    [Write s out somewhere]
    
  • Вы просто переводите назад и вперед в памяти для взаимодействия или чего-то еще? Затем просто выберите кодировку и придерживайтесь ее; 'utf-8', вероятно, лучший выбор для этого:

    u = u'My string'
    s = codecs.encode(u, 'utf-8')
    newu = codecs.decode(s, 'utf-8')
    

В современном программировании вы, вероятно, никогда не захотите использовать кодировку 'ascii' для любого из этого. Это очень маленькое подмножество всех возможных символов, и никакая система, которую я знаю, не использует ее по умолчанию или что-то еще.

Python 3 делает все возможное, чтобы сделать это намного проще, просто изменив имена. В Python 3, str был заменен на bytes, а unicode был заменен на str.

Ответ 4

Это потому, что ваша входная строка не может быть преобразована в соответствии с правилами кодирования (строго по умолчанию).

Я не знаю, но я всегда кодировал с помощью прямого конструктора unicode(), по крайней мере, что в официальной документации :

unicode(your_str, errors="ignore")