UnicodeDecodeError al leer un archivo CSV en Pandas con Python

553

Estoy ejecutando un programa que está procesando 30.000 archivos similares. Un número aleatorio de ellos se detiene y produce este error ...

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 fuente / creación de estos archivos proviene del mismo lugar. ¿Cuál es la mejor manera de corregir esto para continuar con la importación?

1025

read_csvtiene la encodingopción de manejar archivos en diferentes formatos. Utilizo principalmente read_csv('file', encoding = "ISO-8859-1"), o alternativamente encoding = "utf-8"para leer, y generalmente utf-8para to_csv.

También puede usar una de varias aliasopciones como en 'latin'lugar de 'ISO-8859-1'(consulte los documentos de Python , también para muchas otras codificaciones que puede encontrar).

Vea la documentación relevante de Pandas , ejemplos de documentos de Python en archivos csv y muchas preguntas relacionadas aquí en SO. Un buen recurso de fondo es Lo que todo desarrollador debería saber sobre Unicode y conjuntos de caracteres .

Para detectar la codificación (asumiendo que el archivo contiene caracteres no ascii), puede usar enca(ver página de manual ) o file -i(linux) u file -I(osx) (ver página de manual ).

11
  • 13
    Dado que se trata de un problema de Windows, cp1252podría ser preferible iso-8859-1.
    tzot
    7 de junio de 2017 a las 9:28
  • 26
    Gracias pd.read_csv('immigration.csv', encoding = "ISO-8859-1", engine='python')funcionó para mi 1/04/18 a las 19:03
  • 12
    No asuma ciegamente que cierta codificación es la correcta solo porque no se lanza ninguna excepción. Necesita mirar las cadenas y averiguar si la interpretación tiene sentido. Por ejemplo, si obtiene "hors d'½uvre" en lugar de "hors d'œuvre", probablemente necesite cambiar de ISO-8859-1 a ISO-8859-15. 14 de mayo de 2018 a las 8:03
  • 13
    para mí la codificación fue ANSI. Para resolverlo, abrí el csv y notepadluego hice clic save as, allí muestra la codificación al lado del botón Guardar. 17/12/18 a las 12:11
  • 5
    @Ben Este es un buen recurso Lo que todo desarrollador debe saber sobre Unicode y conjuntos de caracteres
    Stefan
    14/06/19 a las 13:53
160

La más simple de todas las soluciones:

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

Solución alternativa:

  • Abra el archivo csv en el editor de texto Sublime o VS Code .
  • Guarde el archivo en formato utf-8.

In sublime, Click File -> Save with encoding -> UTF-8

Luego, puede leer su archivo como de costumbre:

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

y los otros tipos de codificación diferentes son:

encoding = "cp1252"
encoding = "ISO-8859-1"
7
  • 18
    La pregunta explica que hay 30.000 archivos de este tipo. Abrir cada archivo manualmente no sería práctico.
    Keith
    2 de ene. De 2018 a las 20:06
  • 7
    bueno, al menos para un archivo, ¡esto pareció funcionar para mí! 31 de mayo de 2018 a las 14:43
  • 2
    ¡La solución alternativa para guardar con codificación fue realmente útil! aquí se explica cómo usarlo para VSCode stackoverflow.com/questions/30082741/… 13 feb.20 a las 0:20
  • 2
    Gracias por el consejo, guardar el archivo CSV a través de VS Code funcionó para mí.
    talha06
    10/08/20 a las 22:21
  • 2
    Funcionó para mí perfectamente. 21 de ene a las 17:39
29

Pandas permite especificar la codificación, pero no permite ignorar los errores para no reemplazar automáticamente los bytes ofensivos. Por lo tanto, no existe un método único para todos , sino diferentes formas según el caso de uso real.

  1. Conoce la codificación y no hay ningún error de codificación en el archivo. Genial: solo tienes que especificar la codificación:

    file_encoding = 'cp1252'        # set file_encoding to the file encoding (utf8, latin1, etc.)
    pd.read_csv(input_file_and_path, ..., encoding=file_encoding)
    
  2. No quiere que le molesten las preguntas de codificación, y solo quiere que se cargue ese maldito archivo, sin importar si algunos campos de texto contienen basura. Ok, solo tienes que usar la Latin1codificación porque acepta cualquier byte posible como entrada (y lo convierte al carácter Unicode del mismo código):

    pd.read_csv(input_file_and_path, ..., encoding='latin1')
    
  3. Sabe que la mayor parte del archivo está escrito con una codificación específica, pero también contiene errores de codificación. Un ejemplo del mundo real es un archivo UTF8 que se ha editado con un editor que no es utf8 y que contiene algunas líneas con una codificación diferente. Pandas no tiene provisión para un procesamiento de error especial, pero la openfunción Python sí (asumiendo Python3) y read_csvacepta un archivo como un objeto. Los parámetros de errores típicos que se deben usar aquí son los 'ignore'que simplemente suprimen los bytes ofensivos o (en mi humilde opinión, mejor) 'backslashreplace'que reemplazan los bytes ofensivos por la secuencia de escape con barra invertida de 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, ...)
    
1
20
with open('filename.csv') as f:
   print(f)

después de ejecutar este código, encontrará la codificación de 'filename.csv' y luego ejecute el código de la siguiente manera

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

ahi tienes

9

Este es un enfoque de guión más general para la pregunta indicada.

import pandas as pd

encoding_list = ['ascii', 'big5', 'big5hkscs', 'cp037', 'cp273', 'cp424', 'cp437', 'cp500', 'cp720', 'cp737'
                 , 'cp775', 'cp850', 'cp852', 'cp855', 'cp856', 'cp857', 'cp858', 'cp860', 'cp861', 'cp862'
                 , 'cp863', 'cp864', 'cp865', 'cp866', 'cp869', 'cp874', 'cp875', 'cp932', 'cp949', 'cp950'
                 , 'cp1006', 'cp1026', 'cp1125', 'cp1140', 'cp1250', 'cp1251', 'cp1252', 'cp1253', 'cp1254'
                 , 'cp1255', 'cp1256', 'cp1257', 'cp1258', 'euc_jp', 'euc_jis_2004', 'euc_jisx0213', 'euc_kr'
                 , 'gb2312', 'gbk', 'gb18030', 'hz', 'iso2022_jp', 'iso2022_jp_1', 'iso2022_jp_2'
                 , 'iso2022_jp_2004', 'iso2022_jp_3', 'iso2022_jp_ext', 'iso2022_kr', 'latin_1', 'iso8859_2'
                 , 'iso8859_3', 'iso8859_4', 'iso8859_5', 'iso8859_6', 'iso8859_7', 'iso8859_8', 'iso8859_9'
                 , 'iso8859_10', 'iso8859_11', 'iso8859_13', 'iso8859_14', 'iso8859_15', 'iso8859_16', 'johab'
                 , 'koi8_r', 'koi8_t', 'koi8_u', 'kz1048', 'mac_cyrillic', 'mac_greek', 'mac_iceland', 'mac_latin2'
                 , 'mac_roman', 'mac_turkish', 'ptcp154', 'shift_jis', 'shift_jis_2004', 'shift_jisx0213', 'utf_32'
                 , 'utf_32_be', 'utf_32_le', 'utf_16', 'utf_16_be', 'utf_16_le', 'utf_7', 'utf_8', 'utf_8_sig']

for encoding in encoding_list:
    worked = True
    try:
        df = pd.read_csv(path, encoding=encoding, nrows=5)
    except:
        worked = False
    if worked:
        print(encoding, ':\n', df.head())

Uno comienza con todas las codificaciones estándar disponibles para la versión de python (en este caso 3.7 codificaciones estándar de python 3.7 ). Aquí se proporciona una lista de Python utilizable de las codificaciones estándar para las diferentes versiones de Python: Respuesta de desbordamiento de pila útil

Probar cada codificación en una pequeña parte de los datos; solo imprimiendo la codificación de trabajo. El resultado es directamente obvio. Esta salida también aborda el problema de que una codificación como 'latin1' que se ejecuta sin ningún error, no produce necesariamente el resultado deseado.

En el caso de la pregunta, probaría este enfoque específico para el CSVarchivo problemático y luego tal vez intente usar la codificación de trabajo encontrada para todos los demás.

8

En mi caso, un archivo tiene USC-2 LE BOMcodificación, según Notepad ++. Es encoding="utf_16_le"para Python.

Espero que ayude a encontrar una respuesta un poco más rápido para alguien.

0
7

Intente cambiar la codificación. En mi caso, encoding = "utf-16"funcionó.

df = pd.read_csv("file.csv",encoding='utf-16')

2
  • 1
    with open (file) as f: encoding = f.encodingdevuelto cp1252para el archivo con el que estaba trabajando. Sin embargo, especificar encoding = 'utf-16'es lo que me abrió el archivo sin ningún error. Además, configuré engine = 'python'. Gracias por la sugerencia. 22/07/20 a las 11:59
  • 1
    utf-16 funcionó para mí! Todos los casos anteriores - no ( 24 dic.20 a las 11:02
6

Intente especificar el motor = 'python'. Me funcionó, pero todavía estoy tratando de averiguar por qué.

df = pd.read_csv(input_file_path,...engine='python')
1
  • Esto también funcionó para mí. También lo hizo encoding = "ISO-8859-1". Definitivamente es un problema de codificación. Si un carácter especial está codificado en ANSI, como un carácter de elipse (es decir, "..."), e intenta leerlo en UTF-8, es posible que obtenga un error. La conclusión es que debe conocer la codificación con la que se creó el archivo. 11/08/19 a las 16:03
5

En mi caso, esto funcionó para Python 2.7:

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

Y para Python 3, solo:

data = read_csv(filename, encoding = "ISO-8859-1", low_memory=False) 
5

Por favor intente agregar

encoding='unicode_escape'

Esto ayudará. Trabajó para mi. Además, asegúrese de utilizar el delimitador y los nombres de columna correctos.

Puede comenzar cargando solo 1000 filas para cargar el archivo rápidamente.

4

Luché con esto por un tiempo y pensé en publicar esta pregunta, ya que es el primer resultado de búsqueda. Agregar la encoding="iso-8859-1"etiqueta a pandas read_csvno funcionó, ni ninguna otra codificación, siguió dando un UnicodeDecodeError.

Si le está pasando un identificador de archivo pd.read_csv(),, debe poner el encodingatributo en el archivo abierto, no en read_csv. Obvio en retrospectiva, pero un error sutil que rastrear.

4

Estoy publicando una respuesta para proporcionar una solución actualizada y una explicación de por qué puede ocurrir este problema. Supongamos que obtiene estos datos de una base de datos o un libro de Excel. Si tiene caracteres especiales como La Cañada Flintridge city, bueno, a menos que esté exportando los datos usando UTF-8codificación, va a introducir errores. La Cañada Flintridge cityse convertirá La Ca\xf1ada Flintridge city. Si está utilizando pandas.read_csvsin ningún ajuste a los parámetros predeterminados, encontrará el siguiente error

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

Afortunadamente, existen algunas soluciones.

Opción 1 , corrija la exportación. Asegúrese de utilizar la UTF-8codificación.

Opción 2 , si arreglar el problema exportador no está disponible para usted, y que necesita para su uso pandas.read_csv, asegúrese de incluir los siguientes parametros, engine='python'. De forma predeterminada, pandas usa lo engine='C'que es excelente para leer archivos grandes y limpios, pero se bloqueará si surge algo inesperado. En mi experiencia, el entorno encoding='utf-8'nunca ha solucionado esto UnicodeDecodeError. Además, no necesita usar errors_bad_lines, sin embargo, sigue siendo una opción si REALMENTE lo necesita.

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

Opción 3: la solución es mi solución preferida personalmente. Lea el archivo usando 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)

Espero que esto ayude a las personas a encontrar este problema por primera vez.

4

Otro problema importante que enfrenté y que resultó en el mismo error fue:

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

^This line resulted in the same error because I am reading an excel file using read_csv() method. Use read_excel() for reading .xlxs

1
  • Vaya, todos los demás están hablando de problemas de codificación. Parece que mi problema fue peculiar. 21/04/20 a las 20:42
3

Puedes probar esto.

import csv
import pandas as pd
df = pd.read_csv(filepath,encoding='unicode_escape')
2

Esta respuesta parece ser la solución para todos los problemas de codificación CSV. Si tiene un problema de codificación extraño con su encabezado como este:

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

Luego, tiene un carácter de marca de orden de bytes (BOM) al comienzo de su archivo CSV. Esta respuesta aborda el problema:

Python read csv - BOM incrustado en la primera clave

La solución es cargar el CSV con encoding="utf-8-sig":

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

Ojalá esto ayude a alguien.

2

Estoy publicando una actualización de este antiguo hilo. Encontré una solución que funcionó, pero requiere abrir cada archivo. Abrí mi archivo csv en LibreOffice, elegí Guardar como> editar configuración de filtro. En el menú desplegable, elegí la codificación UTF8. Luego agregué encoding="utf-8-sig"al data = pd.read_csv(r'C:\fullpathtofile\filename.csv', sep = ',', encoding="utf-8-sig").

Espero que esto ayude a alguien.

1
  • Nisse, gracias por editar. ¿Puede explicar qué cambió? No veo la diferencia. 1 de ene. De 2019 a las 15:32
2

Tengo problemas para abrir un archivo CSV en chino simplificado descargado de un banco en línea, lo he intentado latin1, lo he intentado iso-8859-1, lo he intentado cp1252, todo fue en vano.

Pero pd.read_csv("",encoding ='gbk')simplemente hace el trabajo.

1

Estoy usando Jupyter-notebook. Y en mi caso, estaba mostrando el archivo en el formato incorrecto. La opción de 'codificación' no funcionaba. Así que guardo el csv en formato utf-8 y funciona.

0

Prueba esto:

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

Parece que se encargará de la codificación sin expresarla explícitamente a través de un argumento

0

Verifique la codificación antes de pasar a pandas. Te ralentizará, pero ...

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

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

En Python 3.7

0

Puedes probar con:

df = pd.read_csv('./file_name.csv', encoding='gbk')

0

A veces, el problema es solo con el archivo .csv. El archivo puede estar dañado. Ante este problema. 'Guarde como' el archivo como csv nuevamente.

0. Open the xls/csv file
1. Go to -> files 
2. Click -> Save As 
3. Write the file name 
4. Choose 'file type' as -> CSV [very important]
5. Click -> Ok 
2
  • No estoy seguro de qué programa usas aquí. ¿Sobresalir? 3 oct.20 a las 18:45
  • abrir archivo de Excel 4/10/20 a las 7:43
0

Pandas no reemplaza automáticamente los bytes ofensivos cambiando el estilo de codificación. En mi caso, cambiar el parámetro de codificación de encoding = "utf-8"a encoding = "utf-16"resolvió el problema.