UnicodeDecodeError lors de la lecture d'un fichier CSV dans Pandas avec Python

412

J'exécute un programme qui traite 30 000 fichiers similaires. Un nombre aléatoire d'entre eux s'arrêtent et produisent cette erreur ...

   File "C:\Importer\src\dfman\importer.py", line 26, in import_chr
     data = pd.read_csv(filepath, names=fields)
   File "C:\Python33\lib\site-packages\pandas\io\parsers.py", line 400, in parser_f
     return _read(filepath_or_buffer, kwds)
   File "C:\Python33\lib\site-packages\pandas\io\parsers.py", line 205, in _read
     return parser.read()
   File "C:\Python33\lib\site-packages\pandas\io\parsers.py", line 608, in read
     ret = self._engine.read(nrows)
   File "C:\Python33\lib\site-packages\pandas\io\parsers.py", line 1028, in read
     data = self._reader.read(nrows)
   File "parser.pyx", line 706, in pandas.parser.TextReader.read (pandas\parser.c:6745)
   File "parser.pyx", line 728, in pandas.parser.TextReader._read_low_memory (pandas\parser.c:6964)
   File "parser.pyx", line 804, in pandas.parser.TextReader._read_rows (pandas\parser.c:7780)
   File "parser.pyx", line 890, in pandas.parser.TextReader._convert_column_data (pandas\parser.c:8793)
   File "parser.pyx", line 950, in pandas.parser.TextReader._convert_tokens (pandas\parser.c:9484)
   File "parser.pyx", line 1026, in pandas.parser.TextReader._convert_with_dtype (pandas\parser.c:10642)
   File "parser.pyx", line 1046, in pandas.parser.TextReader._string_convert (pandas\parser.c:10853)
   File "parser.pyx", line 1278, in pandas.parser._string_box_utf8 (pandas\parser.c:15657)
 UnicodeDecodeError: 'utf-8' codec can't decode byte 0xda in position 6: invalid    continuation byte

La source / création de ces fichiers proviennent tous du même endroit. Quelle est la meilleure façon de corriger cela pour procéder à l'importation?

TravisVOX
la source

Réponses:

824

read_csvprend une encodingoption pour traiter les fichiers dans différents formats. J'utilise principalement read_csv('file', encoding = "ISO-8859-1"), ou alternativement encoding = "utf-8"pour la lecture, et généralement utf-8pour to_csv.

Vous pouvez également utiliser l'une des nombreuses aliasoptions comme 'latin'au lieu de 'ISO-8859-1'(voir la documentation de python , également pour de nombreux autres encodages que vous pouvez rencontrer).

Voir la documentation pertinente de Pandas , des exemples de documents python sur les fichiers csv et de nombreuses questions connexes ici sur SO. Une bonne ressource d'arrière-plan est ce que chaque développeur doit savoir sur les jeux de caractères et unicode .

Pour détecter l'encodage (en supposant que le fichier contient des caractères non ascii), vous pouvez utiliser enca(voir la page de manuel ) ou file -i(linux) ou file -I(osx) (voir la page de manuel ).

Stefan
la source
7
Comme il s'agit d'un problème Windows, il cp1252peut être préférable de le faire iso-8859-1.
tzot
7
Merci a pd.read_csv('immigration.csv', encoding = "ISO-8859-1", engine='python')travaillé pour moi
Mona Jalal
8
Ne présumez pas aveuglément qu'un certain encodage est le bon juste parce qu'aucune exception n'est levée. Vous devez regarder les cordes et déterminer si l'interprétation a du sens. Par exemple, si vous obtenez «hors d'½uvre» au lieu de «hors d'œuvre», vous devrez probablement passer de l'ISO-8859-1 à l'ISO-8859-15.
Joachim Wagner
6
pour moi, l'encodage était ANSI. Pour le comprendre, j'ai ouvert le csv notepadpuis cliquez save as, là, il montre l'encodage à côté du bouton Enregistrer.
Vaibhav Vishal
69

La solution la plus simple de toutes:

import pandas as pd
df = pd.read_csv('file_name.csv', engine='python')

Solution alternative:

  • Ouvrez le fichier csv dans l' éditeur de texte Sublime .
  • Enregistrez le fichier au format utf-8.

En sublime, cliquez sur Fichier -> Enregistrer avec encodage -> UTF-8

Ensuite, vous pouvez lire votre fichier comme d'habitude:

import pandas as pd
data = pd.read_csv('file_name.csv', encoding='utf-8')

et les autres types de codage différents sont:

encoding = "cp1252"
encoding = "ISO-8859-1"
Gil Baggio
la source
11
La question explique qu'il existe 30 000 fichiers de ce type. L'ouverture manuelle de chaque fichier ne serait pas pratique.
Keith
4
bien au moins pour un fichier, cela a semblé fonctionner pour moi!
apil.tamang
Le moteur C est évidemment plus indulgent dans ce qu'il accepte. Pour un fichier CSV particulier qui s'ouvre correctement avec encoding='iso-8859-1', à la place, engine='python'jette _csv.Error: field larger than field limit (131072).
Greg Bacon
1
une solution alternative pour utiliser la sauvegarde avec encodage était vraiment utile! voici comment l'utiliser pour VSCode stackoverflow.com/questions/30082741/…
brownmagik352
20

Pandas permet de spécifier le codage, mais ne permet pas d'ignorer les erreurs pour ne pas remplacer automatiquement les octets incriminés. Il n'y a donc pas de méthode unique , mais des méthodes différentes selon le cas d'utilisation réel.

  1. Vous connaissez l'encodage et il n'y a aucune erreur d'encodage dans le fichier. Génial: il suffit de spécifier l'encodage:

    file_encoding = 'cp1252'        # set file_encoding to the file encoding (utf8, latin1, etc.)
    pd.read_csv(input_file_and_path, ..., encoding=file_encoding)
  2. Vous ne voulez pas être gêné par des questions d'encodage, et ne voulez que ce fichu fichier à charger, peu importe si certains champs de texte contiennent des ordures. Ok, vous n'avez qu'à utiliser l' Latin1encodage car il accepte tout octet possible en entrée (et le convertit en caractère unicode du même code):

    pd.read_csv(input_file_and_path, ..., encoding='latin1')
  3. Vous savez que la plupart du fichier est écrit avec un codage spécifique, mais il contient également des erreurs de codage. Un exemple réel est un fichier UTF8 qui a été édité avec un éditeur non utf8 et qui contient des lignes avec un encodage différent. Pandas n'a aucune disposition pour un traitement d'erreur spécial, mais la openfonction Python a (en supposant Python3), et read_csvaccepte un objet de type fichier. Le paramètre d'erreurs typique à utiliser ici est celui 'ignore'qui supprime simplement les octets incriminés ou (à mon humble avis) 'backslashreplace'qui remplace les octets incriminés par la séquence d'échappement antislashée de leur Python:

    file_encoding = 'utf8'        # set file_encoding to the file encoding (utf8, latin1, etc.)
    input_fd = open(input_file_and_path, encoding=file_encoding, errors = 'backslashreplace')
    pd.read_csv(input_fd, ...)
Serge Ballesta
la source
1
Réponse tardive, mais ciblée sur une question en double ...
Serge Ballesta
14
with open('filename.csv') as f:
   print(f)

après avoir exécuté ce code, vous trouverez l'encodage de 'filename.csv' puis exécutez le code comme suit

data=pd.read_csv('filename.csv', encoding="encoding as you found earlier"

Voilà

bhavesh
la source
6

Dans mon cas, un fichier a un USC-2 LE BOMencodage, selon Notepad ++. C'est encoding="utf_16_le"pour python.

J'espère que cela aide à trouver une réponse un peu plus rapidement pour quelqu'un.

Vodyanikov Andrew Anatolevich
la source
4

Dans mon cas, cela a fonctionné pour python 2.7:

data = read_csv(filename, encoding = "ISO-8859-1", dtype={'name_of_colum': unicode}, low_memory=False) 

Et pour python 3, seulement:

data = read_csv(filename, encoding = "ISO-8859-1", low_memory=False) 
Victor Villacorta
la source
3

Essayez de spécifier le moteur = 'python'. Cela a fonctionné pour moi, mais j'essaie toujours de comprendre pourquoi.

df = pd.read_csv(input_file_path,...engine='python')
Janv33
la source
Cela a également fonctionné pour moi. Codage = "ISO-8859-1" également. C'est définitivement un problème d'encodage. Si un caractère spécial est codé en ANSI, tel qu'un caractère d'ellipse (c'est-à-dire "..."), et que vous essayez de le lire en UTF-8, vous pouvez obtenir une erreur. En bout de ligne, vous devez connaître l'encodage avec lequel le fichier a été créé.
Sean McCarthy
3

Je publie une réponse pour fournir une solution mise à jour et une explication de la raison pour laquelle ce problème peut se produire. Supposons que vous obtenez ces données à partir d'une base de données ou d'un classeur Excel. Si vous avez des caractères spéciaux comme La Cañada Flintridge city, eh bien, sauf si vous exportez les données en utilisant l' UTF-8encodage, vous allez introduire des erreurs. La Cañada Flintridge citydeviendra La Ca\xf1ada Flintridge city. Si vous utilisez pandas.read_csvsans aucun ajustement des paramètres par défaut, vous rencontrerez l'erreur suivante

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf1 in position 5: invalid continuation byte

Heureusement, il existe quelques solutions.

Option 1 , corrigez l'exportation. Assurez-vous d'utiliser l' UTF-8encodage.

Option 2 , si la résolution du problème d' exportation ne sont pas disponibles pour vous, et vous devez utiliser pandas.read_csv, assurez - vous d'inclure les paramters suivants, engine='python'. Par défaut, pandas utilise engine='C'ce qui est idéal pour lire de gros fichiers propres, mais plantera si quelque chose d'inattendu se produit. D'après mon expérience, le réglage encoding='utf-8'n'a jamais résolu ce problème UnicodeDecodeError. En outre, vous n'avez pas besoin d'utiliser errors_bad_lines, cependant, c'est toujours une option si vous en avez vraiment besoin.

pd.read_csv(<your file>, engine='python')

Option 3: la solution est ma solution préférée personnellement. Lisez le fichier en utilisant vanilla Python.

import pandas as pd

data = []

with open(<your file>, "rb") as myfile:
    # read the header seperately
    # decode it as 'utf-8', remove any special characters, and split it on the comma (or deliminator)
    header = myfile.readline().decode('utf-8').replace('\r\n', '').split(',')
    # read the rest of the data
    for line in myfile:
        row = line.decode('utf-8', errors='ignore').replace('\r\n', '').split(',')
        data.append(row)

# save the data as a dataframe
df = pd.DataFrame(data=data, columns = header)

J'espère que cela aidera les personnes rencontrant ce problème pour la première fois.

Jon
la source
2

Je me suis débattu avec cela un moment et j'ai pensé que je posterais sur cette question car c'est le premier résultat de recherche. L'ajout de la encoding="iso-8859-1"balise aux pandas read_csvn'a pas fonctionné, ni aucun autre encodage, a continué à donner un UnicodeDecodeError.

Si vous passez un descripteur de fichier à pd.read_csv(),vous devez mettre l' encodingattribut sur le fichier ouvert, pas dans read_csv. Rétrospectivement évident, mais une erreur subtile à retrouver.

J. Ternent
la source
2

Veuillez essayer d'ajouter

encoding='unicode_escape'

CA aidera. A travaillé pour moi. Assurez-vous également d'utiliser les noms de délimiteur et de colonne corrects.

Vous pouvez commencer par charger seulement 1 000 lignes pour charger rapidement le fichier.

Prakhar Rathi
la source
1

Cette réponse semble être le fourre-tout pour les problèmes d'encodage CSV. Si vous rencontrez un problème de codage étrange avec votre en-tête comme ceci:

>>> f = open(filename,"r")
>>> reader = DictReader(f)
>>> next(reader)
OrderedDict([('\ufeffid', '1'), ... ])

Ensuite, vous avez un caractère de marque d'ordre des octets (BOM) au début de votre fichier CSV. Cette réponse résout le problème:

Python read csv - BOM incorporé dans la première clé

La solution est de charger le CSV avec encoding="utf-8-sig":

>>> f = open(filename,"r", encoding="utf-8-sig")
>>> reader = DictReader(f)
>>> next(reader)
OrderedDict([('id', '1'), ... ])

J'espère que cela aide quelqu'un.

nbwoodward
la source
1

Je poste une mise à jour de cet ancien fil. J'ai trouvé une solution qui a fonctionné, mais nécessite l'ouverture de chaque fichier. J'ai ouvert mon fichier csv dans LibreOffice, choisi Enregistrer sous> modifier les paramètres du filtre. Dans le menu déroulant, j'ai choisi l'encodage UTF8. Ensuite, j'ai ajouté encoding="utf-8-sig"au data = pd.read_csv(r'C:\fullpathtofile\filename.csv', sep = ',', encoding="utf-8-sig").

J'espère que cela aide quelqu'un.

tshirtdr1
la source
Nisse, merci pour le montage. Pouvez-vous expliquer ce que vous avez changé? Je ne vois aucune différence.
tshirtdr1
1

J'ai du mal à ouvrir un fichier CSV en chinois simplifié téléchargé depuis une banque en ligne, j'ai essayé latin1, j'ai essayé iso-8859-1, j'ai essayé cp1252, tout cela en vain.

Mais fait pd.read_csv("",encoding ='gbk')simplement le travail.

Luk Aron
la source
0

J'utilise Jupyter-notebook. Et dans mon cas, il montrait le fichier dans le mauvais format. L'option «encodage» ne fonctionnait pas. Je sauvegarde donc le csv au format utf-8, et ça marche.

Himanshu Sharma
la source
0

Essaye ça:

import pandas as pd
with open('filename.csv') as f:
    data = pd.read_csv(f)

On dirait qu'il va prendre soin de l'encodage sans l'exprimer explicitement par argument

Ke Xu
la source
0

Vérifiez l'encodage avant de passer aux pandas. Cela vous ralentira, mais ...

with open(path, 'r') as f:
    encoding = f.encoding 

df = pd.read_csv(path,sep=sep, encoding=encoding)

En python 3.7

DaveP
la source
0

Un autre problème important que j'ai rencontré et qui a entraîné la même erreur était:

_values = pd.read_csv("C:\Users\Mujeeb\Desktop\file.xlxs")

^ Cette ligne a entraîné la même erreur car je lis un fichier Excel en utilisant la read_csv()méthode. Utiliser read_excel()pour lire .xlxs

Mujeeb Ishaque
la source
Wow, tout le monde parle de problèmes d'encodage. On dirait que mon problème était particulier.
Mujeeb Ishaque
C'est parce que vous avez un read_excelpandas.
Ani Menon
0

Vous pouvez essayer ça.

import csv
import pandas as pd
df = pd.read_csv(filepath,encoding='unicode_escape')
Dileep Dominic
la source