UnicodeDecodeError:'ascii'编解码器无法解码位置23的字节0xc3:序数不在范围内(128)

时间:2014-06-29 10:54:19

标签: python encoding utf-8

当我尝试连接它时,当字段包含'ñ'或'''时,我得到UnicodeDecodeError。如果包含'ñ'或'''的字段是最后一个,则我没有错误。

#...

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

#...

return nombre 

任何想法?非常感谢!

3 个答案:

答案 0 :(得分:54)

您正在编码为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')

但即使是编码也可能为时过早。

经验法则:解码您收到值的那一刻(如果不是API提供的Unicode值),仅在必要时进行编码(如果目标API不直接处理Unicode值)。

答案 1 :(得分:7)

当你得到UnicodeEncodeError时,这意味着你的代码中的某个地方直接将字节字符串转换为unicode字节。默认情况下,它在Python 2中使用ascii编码,并在Python3中使用utf8编码(两者都可能失败,因为并非每个字节在任何编码中都有效)

为避免这种情况,您必须使用显式解码。

如果您的输入文件中有两种不同的编码,其中一种接受任何字节(比如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')

答案 2 :(得分:1)

我在python3中执行时遇到此错误,只需执行 python2

即可完成相同的程序工作
相关问题