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

Когда я пытаюсь объединить это, я получаю UnicodeDecodeError, когда поле содержит 'ñ' или '´'. Если поле, содержащее 'ñ' или '´', является последним, я не получаю ошибки.

#...

nombre = fabrica
nombre = nombre.encode("utf-8") + '-' + sector.encode("utf-8")
nombre = nombre.encode("utf-8") + '-' + unidad.encode("utf-8")

#...

return nombre 

любая идея? Большое спасибо!

4 ответа

Решение

Вы кодируете в UTF-8, затем повторно кодируете в UTF-8. Python может сделать это только в том случае, если он сначала снова декодирует в Unicode, но он должен использовать кодек ASCII по умолчанию:

>>> u'ñ'
u'\xf1'
>>> u'ñ'.encode('utf8')
'\xc3\xb1'
>>> u'ñ'.encode('utf8').encode('utf8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

Не продолжайте кодировать; вместо этого оставьте кодировку в UTF-8 до последнего момента. Вместо этого объедините значения Unicode.

Ты можешь использовать str.join() (или скорее, unicode.join()) здесь, чтобы объединить три значения с тире между:

nombre = u'-'.join(fabrica, sector, unidad)
return nombre.encode('utf-8')

но даже кодирование здесь может быть слишком рано.

Правило большого пальца: декодируйте момент, когда вы получаете значение (если не значения Unicode, уже предоставленные API), кодируйте только тогда, когда это необходимо (если целевой API не обрабатывает значения Unicode напрямую).

Когда вы получаете UnicodeEncodeError, это означает, что где-то в вашем коде вы конвертируете непосредственно байтовую строку в юникодную. По умолчанию в Python 2 он использует кодировку ascii и кодировку utf8 в Python3 (оба могут потерпеть неудачу, поскольку не каждый байт допустим в любой кодировке)

Чтобы избежать этого, вы должны использовать явное декодирование.

Если в вашем входном файле может быть две разные кодировки, одна из которых принимает любой байт (скажем, UTF8 и Latin1), вы можете попытаться сначала преобразовать строку в первую и использовать вторую, если возникает ошибка UnicodeDecodeError.

def robust_decode(bs):
    '''Takes a byte string as param and convert it into a unicode one.
First tries UTF8, and fallback to Latin1 if it fails'''
    cr = None
    try:
        cr = bs.decode('utf8')
    except UnicodeDecodeError:
        cr = bs.decode('latin1')
    return cr

Если вы не знаете оригинальную кодировку и не заботитесь о символах, отличных от ascii, вы можете установить errors параметр decode метод для replace, Любой ошибочный байт будет заменен (из документации стандартной библиотеки):

Заменить на подходящий символ замены; Python будет использовать официальный U+FFFD REPLACEMENT CHARACTER для встроенных кодеков Unicode при декодировании и '?' по кодированию.

bs.decode(errors='replace')

Это решение сработало для моего случая

менять

my_str = str(my_str) #Basically it removes encoding

Я получил эту ошибку при выполнении в Python3, я получил ту же программу, работающую, просто выполнив в python2

Другие вопросы по тегам