UnicodeDecodeError al leer un archivo CSV en Pandas

8 minutos de lectura

Avatar de usuario de TravisVOX
TravisVOX

Estoy ejecutando un programa que procesa 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?

Avatar de usuario de Stefan
stefano

read_csv toma un encoding Opción para tratar archivos en diferentes formatos. Yo uso principalmente read_csv('file', encoding = "ISO-8859-1")o alternativamente encoding = "utf-8" para leer, y en general utf-8 para to_csv.

También puede utilizar uno de varios alias opciones como 'latin' o 'cp1252' (Windows) en lugar de 'ISO-8859-1' (ver documentos de Pythontambién para muchas otras codificaciones que puede encontrar).

Ver 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 debe saber sobre Unicode y conjuntos de caracteres.

Para detectar la codificación (suponiendo que el archivo contiene caracteres que no son ascii), puede usar enca (ver página man) o file -i (Linux) o file -I (osx) (ver página man).

  • @Ben Aquí hay un buen recurso Lo que todo desarrollador debe saber sobre Unicode y conjuntos de caracteres

    – Stefan

    14 de junio de 2019 a las 13:53


  • ISO-8859-1 tiene la propiedad única entre las codificaciones de Python de que puede leer absolutamente cualquier dato binario sin arrojar un error. Muy a menudo, los principiantes probarán diferentes codificaciones sin mirar realmente los datos resultantes, y luego se preguntarán por qué sus resultados son basura cuando eligieron la incorrecta.

    – triplete

    6 abr 2022 a las 17:03


  • @tripleee no hay “codificaciones de Python” (a menos que cuente cosas como implementar ROT-13 como una “codificación” en el sistema de Python); ISO-8859-1 es un estándar reconocido internacionalmente (de ahí ISO) implementado innumerables veces en innumerables entornos. Diez de las dieciséis codificaciones ISO-8859 pueden manejar binarios arbitrarios, al igual que varias páginas de códigos históricas de DOS, codificaciones de texto heredadas de Macintosh y algunas otras. ISO-8859-1 hace Sin embargo, tiene la propiedad (necesariamente) única de que asigna esos bytes a los primeros 256 puntos de código Unicode en orden.

    – Karl Knechtel

    18 de agosto de 2022 a las 1:41

  • Claro, quise decir entre las codificaciones de caracteres que admite Python.

    – triplete

    18 de agosto de 2022 a las 4:38

Avatar de usuario de Gil Baggio
Gil Baggio

La más simple de todas las soluciones:

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

Solución alternativa:

Texto sublime:

  • Abra el archivo csv en Editor de texto sublime o Código VS.
  • Guarde el archivo en formato utf-8.
  • En sublime, haga clic en Archivo -> Guardar con codificación -> UTF-8

Código VS:

En la barra inferior de VSCode, verá la etiqueta UTF-8. Pinchalo. Se abre una ventana emergente. Haga clic en Guardar con codificación. Ahora puede elegir una nueva codificación para ese archivo.

Entonces, podrías leer tu 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"

Pandas permite especificar la codificación, pero no permite ignorar los errores para no reemplazar automáticamente los bytes ofensivos. entonces no hay talla única pero de diferentes maneras dependiendo del 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 desea molestarse con la codificación de preguntas, y solo desea que se cargue ese maldito archivo, sin importar si algunos campos de texto contienen basura. Ok, solo tienes que usar Latin1 codificació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 ha sido editado con un editor que no es utf8 y que contiene algunas líneas con una codificación diferente. Pandas no prevé un procesamiento de errores especial, pero Python open función tiene (asumiendo Python3), y read_csv acepta un archivo como objeto. Los parámetros de errores típicos que se utilizan aquí son 'ignore' que simplemente suprime los bytes ofensivos o (en mi humilde opinión, mejor) 'backslashreplace' que reemplaza 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, ...)
    

Avatar de usuario de Fledias weh
Fledias weh

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 útil de desbordamiento de pila

Probar cada codificación en una pequeña parte de los datos; solo imprimiendo la codificación de trabajo. La salida es directamente obvia. Esta salida también aborda el problema de que una codificación como ‘latin1’ que se ejecuta con algún error, no necesariamente produce el resultado deseado.

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

Avatar de usuario de Prakhar Rathi
prakhar rathi

Intenta agregar

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

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

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

avatar de usuario de bhavesh
bhavesh

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"

ahí vas

avatar de usuario de ah bon
ah buen

Prueba a cambiar la codificación. En mi caso, encoding = "utf-16" trabajó.

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

¿Ha sido útil esta solución?