当我尝试连接它时,当字段包含'ñ'或'''时,我得到UnicodeDecodeError。如果包含'ñ'或'''的字段是最后一个,则我没有错误。
#...
nombre = fabrica
nombre = nombre.encode("utf-8") + '-' + sector.encode("utf-8")
nombre = nombre.encode("utf-8") + '-' + unidad.encode("utf-8")
#...
return nombre
任何想法?非常感谢!
答案 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