web-dev-qa-db-fra.com

Erreur d'encodage Unicode Python

Je lis et analyse un fichier Amazon XML et bien que le fichier XML affiche un ', lorsque j'essaie de l'imprimer, j'obtiens le message d'erreur suivant:

'ascii' codec can't encode character u'\u2019' in position 16: ordinal not in range(128) 

D'après ce que j'ai lu en ligne jusqu'à présent, l'erreur provient du fait que le fichier XML est en UTF-8, mais Python veut le traiter comme un caractère codé ASCII. Existe-t-il un moyen simple d'éliminer l'erreur et de laisser mon programme imprimer le code XML tel qu'il se lit?

96
Alex B

Probablement, votre problème est que vous l'avez analysé correctement et que vous essayez maintenant d'imprimer le contenu du fichier XML et que vous ne pouvez plus le faire, car il existe des caractères Unicode étrangers. Essayez d’encoder d’abord votre chaîne unicode en ascii:

unicodeData.encode('ascii', 'ignore')

la partie "ignorer" lui dira de simplement sauter ces caractères. À partir de la documentation python:

>>> u = unichr(40960) + u'abcd' + unichr(1972)
>>> u.encode('utf-8')
'\xea\x80\x80abcd\xde\xb4'
>>> u.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
UnicodeEncodeError: 'ascii' codec can't encode character '\ua000' in position 0: ordinal not in range(128)
>>> u.encode('ascii', 'ignore')
'abcd'
>>> u.encode('ascii', 'replace')
'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
'&#40960;abcd&#1972;'

Vous voudrez peut-être lire cet article: http://www.joelonsoftware.com/articles/Unicode.html , que j’ai trouvé très utile comme didacticiel de base sur ce qui se passe. Après la lecture, vous finirez par ne plus avoir l'impression de deviner quelles commandes utiliser (ou du moins ce qui m'est arrivé).

178
Scott Stafford

Une meilleure solution:

if type(value) == str:
    # Ignore errors even if the string is not proper UTF-8 or has
    # broken marker bytes.
    # Python built-in function unicode() can do this.
    value = unicode(value, "utf-8", errors="ignore")
else:
    # Assume the value object has proper __unicode__() method
    value = unicode(value)

Si vous souhaitez en savoir plus sur pourquoi:

http://docs.plone.org/manage/troubleshooting/unicode.html#id1

14
Paxwell

Ne codez pas le codage de caractères de votre environnement dans votre script; affiche le texte Unicode directement à la place:

assert isinstance(text, unicode) # or str on Python 3
print(text)

Si votre sortie est redirigée vers un fichier (ou un canal); vous pouvez utiliser PYTHONIOENCODING envvar pour spécifier le codage des caractères:

$ PYTHONIOENCODING=utf-8 python your_script.py >output.utf8

Sinon, python your_script.py devrait fonctionner tel quel - vos paramètres régionaux sont utilisés pour coder le texte (sous POSIX, vérifiez: LC_ALL, LC_CTYPE, LANG envvars - définissez LANG sur un paramètre régional utf-8 si nécessaire).

Pour imprimer Unicode sous Windows, voir cette réponse indiquant comment imprimer Unicode sur une console Windows, dans un fichier ou avec IDLE .

5
jfs

Excellent post: http://www.carlosble.com/2010/12/understanding-python-and-unicode/

# -*- coding: utf-8 -*-

def __if_number_get_string(number):
    converted_str = number
    if isinstance(number, int) or \
            isinstance(number, float):
        converted_str = str(number)
    return converted_str


def get_unicode(strOrUnicode, encoding='utf-8'):
    strOrUnicode = __if_number_get_string(strOrUnicode)
    if isinstance(strOrUnicode, unicode):
        return strOrUnicode
    return unicode(strOrUnicode, encoding, errors='ignore')


def get_string(strOrUnicode, encoding='utf-8'):
    strOrUnicode = __if_number_get_string(strOrUnicode)
    if isinstance(strOrUnicode, unicode):
        return strOrUnicode.encode(encoding)
    return strOrUnicode
1
Ranvijay Sachan

J'ai écrit ce qui suit pour corriger les citations nuisibles non-ASCII et forcer la conversion en quelque chose d’utilisable.

unicodeToAsciiMap = {u'\u2019':"'", u'\u2018':"`", }

def unicodeToAscii(inStr):
    try:
        return str(inStr)
    except:
        pass
    outStr = ""
    for i in inStr:
        try:
            outStr = outStr + str(i)
        except:
            if unicodeToAsciiMap.has_key(i):
                outStr = outStr + unicodeToAsciiMap[i]
            else:
                try:
                    print "unicodeToAscii: add to map:", i, repr(i), "(encoded as _)"
                except:
                    print "unicodeToAscii: unknown code (encoded as _)", repr(i)
                outStr = outStr + "_"
    return outStr
0
user5910

Si vous devez imprimer une représentation approximative de la chaîne à l'écran plutôt que d'ignorer ces caractères non imprimables, veuillez essayer le paquetage unidecode ici:

https://pypi.python.org/pypi/Unidecode

L'explication se trouve ici:

https://www.tablix.org/~avian/blog/archives/2009/01/unicode_transliteration_in_python/

Cela vaut mieux que d'utiliser u.encode('ascii', 'ignore') pour une chaîne donnée u, et cela peut vous éviter des maux de tête inutiles si la précision des caractères ne vous convient pas, mais que vous souhaitez tout de même avoir une lisibilité humaine.

Wirawan

0
Wirawan Purwanto

Python 3.5, 2018

Si vous ne connaissez pas l'encodage mais que l'analyseur unicode rencontre des problèmes, vous pouvez ouvrir le fichier dans Notepad++ et sélectionner Encoding->Convert to ANSI dans la barre du haut. Ensuite, vous pouvez écrire votre python comme ceci

with open('filepath', 'r', encoding='ANSI') as file:
    for Word in file.read().split():
        print(Word)
0
Atomar94

Vous pouvez utiliser quelque chose de la forme

s.decode('utf-8')

qui convertira une chaîne d'octets codée UTF-8 en une chaîne Python Unicode. Mais la procédure exacte à utiliser dépend de la manière dont vous chargez et analysez le fichier XML, par exemple. Si vous n'accédez jamais directement à la chaîne XML, vous devrez peut-être utiliser un objet décodeur du module codecs .

0
David Z