Ответ 1
Вы не можете декодировать unicode
, и вы не можете закодировать str
. Попробуйте сделать это в обратном направлении.
Вот мои попытки с сообщениями об ошибках. Что я делаю не так?
string.decode("ascii", "ignore")
UnicodeEncodeError: кодек 'ascii' не может кодировать символ u '\ xa0' в позиция 37: порядковый номер вне диапазона (128)
string.encode('utf-8', "ignore")
UnicodeDecodeError: кодек "ascii" не может декодировать байт 0xc2 в позиции 37: порядковый номер вне диапазона (128)
Вы не можете декодировать unicode
, и вы не можете закодировать str
. Попробуйте сделать это в обратном направлении.
Угадывая все вещи, опущенные из исходного вопроса, но, предполагая, что 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)
Помимо получения 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
.
Это потому, что ваша входная строка не может быть преобразована в соответствии с правилами кодирования (строго по умолчанию).
Я не знаю, но я всегда кодировал с помощью прямого конструктора unicode(), по крайней мере, что в официальной документации :
unicode(your_str, errors="ignore")