web-dev-qa-db-fra.com

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

comment fonctionne la chose unicode sur python2? je ne comprends tout simplement pas.

ici, je télécharge des données depuis un serveur et les analyse pour 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

je vous remercie!!

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

51
ihucos

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

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

Cela gérera tous les trémas susceptibles d’être insérés dans le message JSON.

Vous devriez lire le Le minimum absolu de Joel Spolsky Chaque développeur de logiciels doit absolument savoir positivement sur Unicode et les jeux de caractères (Aucune excuse!) . J'espère que cela clarifiera certains problèmes que vous rencontrez autour d'Unicode.

Ma solution est un peu drôle.J'ai jamais pensé que ce serait aussi simple que de sauvegarder avec le codec UTF-8.J’utilise notepad ++ (v5.6.8). Je n’ai pas remarqué que je l’avais enregistré avec le codec ANSI initialement. J'utilise un fichier séparé pour placer tous les dictionnaires localisés. J'ai trouvé ma solution dans l'onglet 'Encodage' de mon bloc-notes ++. Je sélectionnais 'Encodage en UTF-8 sans nomenclature' et je l'enregistrais. Cela fonctionne avec brio.

6
rolypoly

L'erreur que vous voyez signifie que les données que vous recevez de l'extrémité distante ne sont pas du code JSON valide. JSON (selon les spécifications) est normalement UTF-8, mais peut également être UTF-16 ou UTF-32 (en grand ou en petit bout.) L'erreur exacte que vous voyez signifie qu'une partie des données n'était pas UTF-8 valide (et n'était pas non plus UTF-16 ou UTF-32, car cela produirait des erreurs différentes.)

Vous devriez peut-être examiner la réponse que vous recevez de l'extrémité distante au lieu de transmettre aveuglément les données à json.loads(). À l'heure actuelle, vous lisez toutes les données de la réponse dans une chaîne et supposez qu'il s'agit de JSON. Au lieu de cela, vérifiez le type de contenu de la réponse. Assurez-vous que la page Web prétend réellement vous donner du code JSON et non, par exemple, un message d'erreur indiquant que n'est pas JSON.

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

4
Thomas Wouters

La solution pour changer le codage en Latin1/ISO-8859-1 résout un problème que j'ai observé avec html2text.py comme invoqué sur une sortie de tex4ht. J'utilise cela pour un décompte Word automatisé sur des documents LaTeX: tex4ht les convertit en HTML, puis html2text.py les décompose en texte pur pour les compter ultérieurement via wc -w. Maintenant, si, par exemple, un "Umlaut" allemand entre par une entrée de base de données de littérature, ce processus échouerait comme html2text.py se plaindrait, par exemple.

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

Par la suite, ces erreurs seraient par la suite particulièrement difficiles à localiser et vous souhaiterez essentiellement avoir le tréma dans votre section de références. Un simple changement dans html2text.py de

data = data.decode (encoding)

à

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 le codage comme deuxième paramètre et épargner la modification.

3
Matthias Nott

Collez ceci sur votre ligne de commande:

export LC_CTYPE="en_US.UTF-8" 
1
Mark Francis

Juste au cas où quelqu'un aurait le même problème. J'utilise vim avec YouCompleteMe , impossible de 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.

1
hylepo

Dans votre Android_suggest.py, divisez cette déclaration monstrueuse de retour en une ligne en un seul morceau. Enregistrez repr(string_passed_to_json.loads) quelque part afin qu'il puisse être vérifié après une exception. Eye-ball les résultats. Si le problème n'est pas évident, modifiez votre question pour afficher le repr.

0
John Machin

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

urlopen().read() renvoie des octets et vous devez les décoder en chaînes unicode. De plus, il serait utile de vérifier le correctif depuis http://bugs.python.org/issue4733

0
sorin