UnicodeDecodeError
указывает, что ошибка происходит во время декодирования байтовой строки в Unicode.
В частности, это может произойти, если вы попытаетесь кодировать строку байтов вместо строки Юникода в Python 2:
>>> u"\N{EM DASH}".encode('utf-8').encode('utf-8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
u"\N{EM DASH}".encode('utf-8')
является байтовой строкой и вызывает .encode('utf-8')
, второй раз приводит к неявному .decode(sys.getdefaultencoding())
, что приводит к UnicodeDecodeError
.
Чем отличается IDE от того, что она не попадает в эту ошибку?
Вероятно, он работает в IDE, потому что он меняет sys.getdefaultencoding()
на utf-8
, что не следует делать . Это может скрыть ошибки, как показывает ваш вопрос. В общем, это также может привести к поломке сторонних библиотек, которые не ожидают не-ascii sys.getdefaultencoding()
на Python 2.
Я кодирую обе строки Юникода, потому что это единственный способ проверить одну строку на другую, содержащую буквы типа - или ç.
Вы должны использовать unicodedata.normalize()
вместо :
>>> import unicodedata
>>> a, b = u'\xf1', u'n\u0303'
>>> print(a)
ñ
>>> print(b)
ñ
>>> a == unicodedata.normalize('NFC', b)
True
Примечание: код в вашем вопросе может дать удивительные результаты:
#XXX BROKEN, DON'T DO IT
...address_name.upper() in i[5].upper().encode('utf-8')...
address_name.upper()
вызывает метод bytes.upper
, а i[5].upper()
вызывает метод unicode.upper
. Первый не поддерживает Unicode и может зависеть от текущей локали, последний лучше, но для сравнения без учета регистра используйте вместо этого метод .casefold()
:
key = unicode_address_name.casefold()
... if key == i[5].casefold()...
В общем, если вам нужно отсортировать строки в юникоде, вы можете использовать icu.Collator
. Сравните лексикографическую сортировку по умолчанию:
>>> L = [u'sandwiches', u'angel delight', u'custard', u'éclairs', u'glühwein']
>>> sorted(L)
[u'angel delight', u'custard', u'gl\xfchwein', u'sandwiches', u'\xe9clairs']
при заказе на en_GB
язык:
>>> import icu # PyICU
>>> collator = icu.Collator.createInstance(icu.Locale('en_GB'))
>>> sorted(L, key=collator.getSortKey)
[u'angel delight', u'custard', u'\xe9clairs', u'gl\xfchwein', u'sandwiches']