Erreur de codage Python Unicode


104

Je lis et analyse un fichier XML Amazon et tandis que le fichier XML affiche un ', lorsque j'essaie de l'imprimer, j'obtiens l'erreur suivante:

'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 vient du fait que le fichier XML est en UTF-8, mais Python veut le gérer comme un caractère encodé ASCII. Existe-t-il un moyen simple de faire disparaître l'erreur et de faire imprimer le XML par mon programme au fur et à mesure?


Je venais juste à SO pour poster cette question. Existe-t-il un moyen simple de désinfecter une chaîne unicode()?
Nick Heiner du

Veuillez également vérifier cette réponse à une question connexe: "Python UnicodeDecodeError - Suis-je mal compris encoder?"
tzot le

Réponses:


193

Probablement, votre problème est que vous l'avez bien analysé, et maintenant vous essayez d'imprimer le contenu du XML et vous ne pouvez pas parce qu'il y a des caractères Unicode étrangers. Essayez d'abord d'encoder 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 tutoriel de base sur ce qui se passe. Après la lecture, vous cesserez de vous sentir comme si vous deviez juste quelles commandes utiliser (ou du moins cela m'est arrivé).


1
J'essaie de sécuriser la chaîne suivante: 'foo “bar bar” df' (notez les guillemets bouclés), mais ce qui précède échoue toujours pour moi.
Nick Heiner du

@Rosarch: échoue comment? même erreur? Et quelle règle de gestion des erreurs avez-vous utilisée?
Scott Stafford

@Rosarch, votre problème est probablement antérieur. Essayez ce code: # - - codage: latin-1 - - u = u 'foo “bar bar” df' print u.encode ('ascii', 'ignore') Pour vous, il s'agissait probablement de convertir votre chaîne EN unicode donné l'encodage que vous avez spécifié pour le script python qui a généré l'erreur.
Scott Stafford

Je suis allé de l'avant et j'ai fait de mon problème sa propre question: stackoverflow.com/questions/3224427/…
Nick Heiner

1
.encode('ascii', 'ignore')perd des données inutilement même si l'environnement d'OP peut prendre en charge les caractères non-ascii (la plupart des cas)
jfs

16

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 les raisons:

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


3
Cela n'aide pas avec le problème d'OP: "Impossible d'encoder le caractère u '\ u2019'" . u'\u2019est déjà Unicode.
jfs

6

Ne codez pas en dur le codage des caractères de votre environnement dans votre script; imprimer 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 tube); vous pouvez utiliser PYTHONIOENCODINGenvvar, pour spécifier le codage des caractères:

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

Dans le cas contraire, python your_script.pydevrait fonctionner comme cela est - vos paramètres régionaux sont utilisés pour coder le texte (à l' enregistrement POSIX: LC_ALL, LC_CTYPE, LANGenvvars - ensemble LANGà un lieu utf-8 si nécessaire).

Pour imprimer Unicode sous Windows, consultez cette réponse qui montre comment imprimer Unicode sur la console Windows, dans un fichier ou en utilisant IDLE .


1

Excellent article: 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

0

Vous pouvez utiliser quelque chose du formulaire

s.decode('utf-8')

qui convertira une chaîne d'octets encodée en UTF-8 en une chaîne Python Unicode. Mais la procédure exacte à utiliser dépend exactement 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 codecsmodule .


Il est déjà codé en UTF-8 L'erreur est spécifiquement: myStrings = deque ([u'Dorf and Svoboda \ u2019s text build on the str ... and Computer Engineering \ u2019s subdisciplines. ']) La chaîne est en UTF-8 comme vous pouvez le voir, mais il s'énerve contre le '\ u2019' interne
Alex B

Oh, OK, je pensais que tu avais un problème différent.
David Z du

7
@Alex B: Non, la chaîne est Unicode, pas Utf-8. Pour l' encoder comme Utf-8, utilisez'...'.encode('utf-8')
qch

0

J'ai écrit ce qui suit pour corriger les citations non-ascii nuisibles et forcer la conversion en quelque chose 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

Si vous avez besoin d'imprimer une représentation approximative de la chaîne à l'écran, plutôt que d'ignorer ces caractères non imprimables, veuillez essayer le unidecodepackage 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/

C'est mieux que d'utiliser le u.encode('ascii', 'ignore')pour une chaîne donnée u, et peut vous éviter des maux de tête inutiles si la précision des caractères n'est pas ce que vous recherchez, mais que vous souhaitez toujours avoir une lisibilité humaine.

Wirawan


-1

Essayez d'ajouter la ligne suivante en haut de votre script python.

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

-1

Python 3.5, 2018

Si vous ne connaissez pas le codage mais que l'analyseur Unicode a des problèmes, vous pouvez ouvrir le fichier dans Notepad++et dans la barre supérieure, sélectionnez Encoding->Convert to ANSI. Ensuite, vous pouvez écrire votre python comme ça

with open('filepath', 'r', encoding='ANSI') as file:
    for word in file.read().split():
        print(word)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.