web-dev-qa-db-fra.com

UnicodeDecodeError: le codec 'ascii' ne peut pas décoder l'octet 0xc3 en position 23: l'ordinal n'est pas dans la plage (128)

lorsque j'essaie de concaténer cela, j'obtiens UnicodeDecodeError lorsque le champ contient 'ñ' ou '´'. Si le champ contenant le "ñ" ou le "´" est le dernier, aucune erreur ne se produit.

#...

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

#...

return nombre 

une idée? Merci beaucoup!

45
Capens

Vous encodez en UTF-8, alors re - encodez en UTF-8. Python ne peut le faire que s'il commence décode à nouveau en Unicode, mais doit utiliser la valeur par défaut ASCII codec:

>>> 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)

Ne continuez pas à encoder; laissez l'encodage à UTF-8 jusqu'au dernier moment possible à la place. Concaténez plutôt les valeurs Unicode.

Vous pouvez utiliser str.join() (ou plutôt unicode.join()) ici pour concaténer les trois valeurs avec des tirets entre:

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

mais même l'encodage ici est peut-être trop tôt.

Règle générale: décoder le moment où vous recevez la valeur (si les valeurs Unicode fournies par une API ne sont pas déjà fournies), n'encodez que lorsque vous devez le faire (si l'API de destination ne gère pas directement les valeurs Unicode).

55
Martijn Pieters

Lorsque vous obtenez un UnicodeEncodeError, cela signifie que quelque part dans votre code, vous convertissez directement une chaîne d'octets en une chaîne unicode. Par défaut, dans Python 2, il utilise le codage ascii et le codage utf8 en Python3 (les deux peuvent échouer car tous les octets ne sont valides dans aucun des codages).

Pour éviter cela, vous devez utiliser un décodage explicite.

Si vous avez 2 codages différents dans votre fichier d’entrée, l’un d’eux accepte n’importe quel octet (disons UTF8 et Latin1), vous pouvez essayer de convertir d’abord une chaîne en premier et d’utiliser le second en cas d’apparition de 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

Si vous ne connaissez pas l'encodage d'origine et ne vous souciez pas des caractères non ascii, vous pouvez définir le paramètre facultatif errors de la méthode decode sur replace. Tout octet incriminé sera remplacé (à partir de la documentation de la bibliothèque standard):

Remplacez-le par un personnage de remplacement approprié. Python utilisera le caractère officiel de remplacement U + FFFD pour les codecs Unicode intégrés lors du décodage et le codage ‘?’ Pour le codage.

bs.decode(errors='replace')
7
Serge Ballesta

J'obtenais cette erreur lors de l'exécution en python3, j'ai obtenu le même programme en exécutant simplement dans python2

0
Jose Kj