UnicodeDecodeError:'ascii'编解码器无法解码位置23的字节0xc3:序数不在范围(128)内
当我尝试把这些内容连接在一起时,如果字段里有'ñ'或'´',就会出现UnicodeDecodeError的错误。如果包含'ñ'或'´'的字段是最后一个,那就不会出错。
#...
nombre = fabrica
nombre = nombre.encode("utf-8") + '-' + sector.encode("utf-8")
nombre = nombre.encode("utf-8") + '-' + unidad.encode("utf-8")
#...
return nombre
有什么想法吗?非常感谢!
3 个回答
我在用python3运行时遇到了这个错误,但我只需在 python2
中运行同样的程序就能正常工作。
当你遇到一个 UnicodeEncodeError
错误时,这意味着在你的代码中,有地方把字节字符串直接转换成了Unicode字符串。在Python 2中,默认使用的是ascii编码,而在Python 3中则使用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字符,你可以把 decode
方法的可选参数 errors
设置为 replace
。这样,任何有问题的字节都会被替换掉(来自标准库文档):
用合适的替代字符替换;Python在解码时会使用官方的U+FFFD替代字符,而在编码时则用‘?’。
bs.decode(errors='replace')
你现在是把内容编码成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值)。