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