51 votes

UnicodeDecodeError : Le codec 'utf8' ne peut pas décoder les octets en position 3-6 : données invalides.

Comment le truc de l'unicode fonctionne-t-il sur python2 ? je ne le comprends pas.

Ici, je télécharge des données à partir d'un serveur et je les analyse en JSON.

Traceback (most recent call last):
  File "/usr/local/lib/python2.6/dist-packages/eventlet-0.9.12-py2.6.egg/eventlet/hubs/poll.py", line 92, in wait
    readers.get(fileno, noop).cb(fileno)
  File "/usr/local/lib/python2.6/dist-packages/eventlet-0.9.12-py2.6.egg/eventlet/greenthread.py", line 202, in main
    result = function(*args, **kwargs)
  File "android_suggest.py", line 60, in fetch
    suggestions = suggest(chars)
  File "android_suggest.py", line 28, in suggest
    return [i['s'] for i in json.loads(opener.open('https://market.android.com/suggest/SuggRequest?json=1&query='+s+'&hl=de&gl=DE').read())]
  File "/usr/lib/python2.6/json/__init__.py", line 307, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python2.6/json/decoder.py", line 319, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python2.6/json/decoder.py", line 336, in raw_decode
    obj, end = self._scanner.iterscan(s, **kw).next()
  File "/usr/lib/python2.6/json/scanner.py", line 55, in iterscan
    rval, next_pos = action(m, context)
  File "/usr/lib/python2.6/json/decoder.py", line 217, in JSONArray
    value, end = iterscan(s, idx=end, context=context).next()
  File "/usr/lib/python2.6/json/scanner.py", line 55, in iterscan
    rval, next_pos = action(m, context)
  File "/usr/lib/python2.6/json/decoder.py", line 183, in JSONObject
    value, end = iterscan(s, idx=end, context=context).next()
  File "/usr/lib/python2.6/json/scanner.py", line 55, in iterscan
    rval, next_pos = action(m, context)
  File "/usr/lib/python2.6/json/decoder.py", line 155, in JSONString
    return scanstring(match.string, match.end(), encoding, strict)
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 3-6: invalid data

Merci !

EDIT : la chaîne suivante provoque l'erreur : '[{"t":"q","s":"abh\xf6ren"}]' . \xf6 doit être décodé en ö (abhören)

83voto

La chaîne que vous essayez d'analyser en tant que JSON n'est pas codée en UTF-8. Elle est très probablement encodée en ISO-8859-1. Essayez ce qui suit :

json.loads(unicode(opener.open(...), "ISO-8859-1"))

Cela permettra de gérer tous les trémas qui pourraient se trouver dans le message JSON.

Vous devriez lire le livre de Joel Spolsky. Le minimum absolu que tout développeur de logiciels doit absolument, positivement connaître sur Unicode et les jeux de caractères (pas d'excuses !) . J'espère que cela permettra de clarifier certains problèmes que vous rencontrez autour d'Unicode.

4voto

Thomas Wouters Points 38811

L'erreur que vous voyez signifie que les données que vous recevez de l'extrémité distante ne sont pas du JSON valide. JSON (selon la spécification) est normalement UTF-8, mais peut également être UTF-16 ou UTF-32 (en big- ou little-endian). L'erreur exacte que vous voyez signifie qu'une partie des données n'était pas valide UTF-8 (et n'était pas non plus UTF-16 ou UTF-32, car ceux-ci produiraient des erreurs différentes).

Peut-être devriez-vous examiner la réponse réelle que vous recevez de l'extrémité distante, au lieu de transmettre aveuglément les données à l'adresse suivante json.loads() . Pour l'instant, vous lisez toutes les données de la réponse dans une chaîne et supposez qu'il s'agit de JSON. Vérifiez plutôt le type de contenu de la réponse. Assurez-vous que la page Web prétend effectivement vous donner JSON et non, par exemple, un message d'erreur qui n'est pas JSON.

(Aussi, après avoir vérifié la réponse, utilisez json.load() en lui passant l'objet de type fichier retourné par opener.open() au lieu de lire toutes les données dans une chaîne de caractères et de les transmettre à l'utilisateur. json.loads() .)

3voto

Matthias Nott Points 21

La solution de changer l'encodage en Latin1 / ISO-8859-1 résout un problème que j'ai observé avec html2text.py invoqué sur une sortie de tex4ht. Je l'utilise pour un comptage automatique des mots sur les documents LaTeX : tex4ht les convertit en HTML, puis html2text.py les réduit en texte pur pour un comptage ultérieur par wc -w. Maintenant, si, par exemple, un "Umlaut" allemand arrive par le biais d'une entrée de la base de données de la littérature, ce processus échouerait car html2text.py se plaindrait par exemple de ce qui suit

UnicodeDecodeError : Le codec 'utf8' ne peut pas décoder les octets en position 32243-32245 : données non valides.

Ces erreurs seraient alors particulièrement difficiles à repérer, et vous voulez essentiellement avoir le Umlaut dans votre section de références. Un simple changement dans html2text.py de

données = données.décoder(encodage)

à

data = data.decode("ISO-8859-1")

résout ce problème ; si vous appelez le script en utilisant le fichier HTML comme premier paramètre, vous pouvez également passer l'encodage comme second paramètre et épargner la modification.

1voto

hylepo Points 47

Juste au cas où quelqu'un aurait le même problème. J'utilise vim avec YouCompleteMe n'a pas réussi à démarrer ycmd avec ce message d'erreur, ce que j'ai fait est : export LC_CTYPE="en_US.UTF-8" le problème a disparu.

0voto

sorin Points 23747

Solution temporaire : unicode(urllib2.urlopen(url).read(), 'utf8') - cela devrait fonctionner si ce qui est renvoyé est UTF-8.

urlopen().read() retournent des octets et vous devez les décoder en chaînes unicode. Il serait également utile de vérifier le patch de http://bugs.python.org/issue4733

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X