124 votes

UnicodeDecodeError : le codec 'ascii' ne peut pas décoder l'octet 0xd1 en position 2 : l'ordinal n'est pas compris dans l'intervalle(128)

J'essaie de travailler avec un très grand ensemble de données qui contient des caractères non standard. Je dois utiliser unicode, conformément aux spécifications du travail, mais je suis déconcerté. (Et il est fort possible que je fasse tout de travers).

J'ouvre le fichier CSV en utilisant :

 15     ncesReader = csv.reader(open('geocoded_output.csv', 'rb'), delimiter='\t', quotechar='"')

Ensuite, je tente de l'encoder avec :

name=school_name.encode('utf-8'), street=row[9].encode('utf-8'), city=row[10].encode('utf-8'), state=row[11].encode('utf-8'), zip5=row[12], zip4=row[13],county=row[25].encode('utf-8'), lat=row[22], lng=row[23])

J'encode tout sauf la lat et la lng car elles doivent être envoyées à une API. Lorsque j'exécute le programme pour analyser le jeu de données afin de l'utiliser, j'obtiens le Traceback suivant.

Traceback (most recent call last):
  File "push_into_db.py", line 80, in <module>
    main()
  File "push_into_db.py", line 74, in main
    district_map = buildDistrictSchoolMap()
  File "push_into_db.py", line 32, in buildDistrictSchoolMap
    county=row[25].encode('utf-8'), lat=row[22], lng=row[23])
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd1 in position 2: ordinal not in range(128)

Je pense que je dois vous dire que j'utilise python 2.7.2, et que cela fait partie d'une application construite sur django 1.4. J'ai lu plusieurs posts sur ce sujet, mais aucun ne semble s'appliquer directement. Toute aide sera grandement appréciée.

Sachez également que certains des caractères non standard à l'origine du problème sont Ñ et peut-être É.

163voto

ch3ka Points 3644

Unicode n'est pas égal à UTF-8. Ce dernier n'est qu'un codage pour les premiers.

Vous vous y prenez à l'envers. Vous êtes lecture UTF-8- codé données, vous devez donc décoder la chaîne encodée en UTF-8 en une chaîne unicode.

Il suffit donc de remplacer .encode con .decode et cela devrait fonctionner (si votre fichier .csv est encodé en UTF-8).

Mais il n'y a pas de quoi avoir honte. Je parie que 3 programmeurs sur 5 ont eu du mal à comprendre cela au début, si ce n'est plus ;)

Mise à jour : Si vos données d'entrée sont no encodé en UTF-8, vous devez alors .decode() avec l'encodage approprié, bien sûr. Si rien n'est donné, python suppose qu'il s'agit d'ASCII, ce qui échoue évidemment pour les caractères non ASCII.

99voto

khelili miliana Points 2436

Il suffit d'ajouter les lignes suivantes à votre code :

1.Python2

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

2.Python3

import sys
from importlib import reload
reload(sys)
sys.setdefaultencoding('utf-8')

44voto

screaminghard Points 201

Pour les utilisateurs de Python 3, vous pouvez faire

with open(csv_name_here, 'r', encoding="utf-8") as f:
    #some codes

cela fonctionne aussi avec flask :)

10voto

Temi Fakunle Points 97

La raison principale de l'erreur est que l'encodage par défaut supposé par python est ASCII. Par conséquent, si les données de la chaîne doivent être encodées par encode('utf8') contient un caractère en dehors de la plage ASCII, par exemple pour une chaîne comme 'hgvcj터파크387', python lèverait une erreur parce que la chaîne n'est pas dans le format d'encodage attendu.

Si vous utilisez une version de python antérieure à la version 3.5, une solution fiable consisterait à définir l'encodage par défaut supposé par python comme suit utf8 :

import sys
reload(sys)
sys.setdefaultencoding('utf8')
name = school_name.encode('utf8')

De cette manière, Python serait en mesure d'anticiper les caractères d'une chaîne qui se situent en dehors de la plage ASCII.

Cependant, si vous utilisez la version 3.5 ou supérieure de python, la fonction reload() n'est pas disponible, vous devrez donc la corriger en utilisant decode, par exemple.

name = school_name.decode('utf8').encode('utf8')

3voto

Prithvi Points 33

Pour les utilisateurs de Python 3 :

le passage de l'encodage "ascii" à l'encodage "latin1" fonctionne.

Vous pouvez également essayer de trouver l'encodage automatiquement en lisant les 10000 premiers octets à l'aide de l'extrait ci-dessous :

import chardet  
with open("dataset_path", 'rb') as rawdata:  
            result = chardet.detect(rawdata.read(10000))  
print(result)

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