Menu

CSV en Python: leer y escribir archivos CSV con el módulo csv

Cómo leer y escribir archivos CSV en Python — el módulo csv, DictReader y DictWriter, manejar cabeceras, entrecomillado y cuándo recurrir a pandas en su lugar.

CSV es más simple de lo que parece (y más tramposo de lo que esperarías)

Un archivo CSV es solo texto: filas separadas por saltos de línea, campos separados por comas. Esa es la idea. En la práctica, te topas con strings entrecomillados que contienen comas, campos con saltos de línea incrustados, distintas convenciones regionales (coma vs punto y coma), archivos guardados desde Excel que incluyen un BOM — suficientes casos borde como para que escribir tu propio line.split(",") casi siempre sea un error.

El módulo incorporado csv de Python maneja todo eso. Raramente necesitarás algo más para archivos de pequeños a medianos.

Leer un CSV con csv.reader

csv.reader produce cada fila como una lista de strings:

import csv

with open("people.csv", newline="") as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

Unos cuantos detalles no obvios:

  • Pasa siempre newline="" a open. El módulo csv maneja los finales de línea por sí mismo; sin esto, obtienes filas en blanco extra en Windows.
  • Cada valor es un string. "42" se queda como string hasta que llames a int(...). CSV no tiene tipos.
  • La fila de cabeceras es solo otra fila. Si tu archivo tiene cabeceras, o sáltate la primera fila manualmente o pásate a DictReader.

Saltarse la fila de cabeceras

import csv

with open("people.csv", newline="") as f:
    reader = csv.reader(f)
    headers = next(reader)         # saca la primera fila
    for row in reader:
        print(row)

next(reader) avanza el iterador en uno y devuelve esa fila.

Leer como dicts con DictReader

csv.DictReader trata la primera fila como cabeceras y te da cada fila siguiente como un dict:

import csv

with open("people.csv", newline="") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row["name"], row["email"])

Esto es casi siempre lo que quieres. Los nombres de columna se autodocumentan, y reordenar columnas en el archivo fuente no rompe tu código.

Si el archivo no tiene cabeceras, pásalas explícitamente con fieldnames=["name", "email", ...].

Escribir un CSV con csv.writer

csv.writer convierte filas (listas) en líneas CSV:

import csv

rows = [
    ["name", "age", "city"],
    ["Rosa", 30, "Lisbon"],
    ["Ada", 36, "London"],
]

with open("out.csv", "w", newline="") as f:
    writer = csv.writer(f)
    writer.writerows(rows)

writerow(row) escribe una sola fila; writerows(rows) escribe un iterable entero de una vez. Ambos entrecomillan campos automáticamente cuando contienen comas, comillas o saltos de línea — no tienes que pensarlo.

Escribir dicts con DictWriter

Cuando tus datos ya están en forma de dict, DictWriter se salta el paso de "convertir a lista":

import csv

people = [
    {"name": "Rosa", "age": 30, "city": "Lisbon"},
    {"name": "Ada", "age": 36, "city": "London"},
]

with open("out.csv", "w", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=["name", "age", "city"])
    writer.writeheader()
    writer.writerows(people)

El argumento fieldnames controla tanto la cabecera como el orden de las columnas. Las claves en tus dicts que no están en fieldnames se descartan silenciosamente (o puedes hacer que lance con extrasaction="raise").

Separadores distintos y entrecomillado

No todo "CSV" usa comas. Las localizaciones europeas a menudo usan ;, los archivos separados por tabuladores usan \t, algunos sistemas usan |. Pasa un argumento delimiter=:

import csv

with open("data.tsv", newline="") as f:
    reader = csv.reader(f, delimiter="\t")
    for row in reader:
        print(row)

Para archivos con reglas de entrecomillado inusuales, csv.register_dialect(...) te deja configurar una vez y reutilizar. Para la mayoría de archivos, los defaults más delimiter= bastan.

Encoding

Los archivos CSV son texto — tienen encodings. UTF-8 es el default moderno; los archivos originados en Excel en Windows a veces usan cp1252 o incluyen un BOM UTF-8. Sé explícito:

with open("data.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    ...

Si ves UnicodeDecodeError, el archivo no está en el encoding que adivinaste. Prueba utf-8-sig (maneja el BOM de Excel), cp1252 o latin-1 como los sospechosos comunes.

Convertir filas CSV en tipos útiles

Como cada valor llega como string, parsear es cosa tuya:

main.py
Output
Click Run to see the output here.

(StringIO nos deja ejecutar el ejemplo sin un archivo real — en código real harías open(path).)

Para CSVs con tipos complicados (fechas, números nullable, true/false en diez escrituras distintas), considera pandas — tiene convenciones para la mayoría incorporadas.

Cuándo recurrir a pandas

pandas.read_csv(path) devuelve un DataFrame, que es la estructura correcta en el momento en que quieres:

  • Filtrar filas: df[df["active"] == True]
  • Agregar: df.groupby("city")["age"].mean()
  • Hacer join con otra tabla
  • Escribir de vuelta con formato simple
import pandas as pd

df = pd.read_csv("people.csv")
adults = df[df["age"] >= 18]
adults.to_csv("adults.csv", index=False)

Pandas es sobredimensionado para lecturas pequeñas y lineales — y es una dependencia pesada (instálala con pip en un entorno virtual). Pero para cualquier cosa con forma de datos, es la herramienta a la que recurren la mayoría de analistas Python.

Streaming de archivos muy grandes

csv.reader ya es perezoso — lee una fila a la vez. Mantenlo así iterando (no llamando a list(reader) al principio), y tu memoria se queda plana independientemente del tamaño del archivo:

import csv

with open("huge.csv", newline="") as f:
    reader = csv.DictReader(f)
    error_count = 0
    for row in reader:
        if row["status"] == "error":
            error_count += 1

print(f"Found {error_count} errors.")

Eso maneja un archivo de 10 GB igual de feliz que uno de 10 KB, mientras no acumules las filas en una lista.

Unos cuantos hábitos

  • Pasa siempre newline="" a open al leer o escribir CSVs.
  • Usa DictReader/DictWriter cuando el archivo tenga cabeceras — más legible que índices enteros.
  • Sé explícito sobre el encoding, especialmente con archivos de Excel o de fuentes no en inglés.
  • Convierte los tipos justo en el paso de lectura para que el código de abajo no tenga que hacerlo.
  • Recurre a pandas cuando quieras analizar los datos, no solo moverlos.

Siguiente

Ahora puedes leer JSON y CSV. La última habilidad del mundo real que cubriremos es traer datos por red — eso es la siguiente página, sobre peticiones HTTP con la librería requests.

Preguntas frecuentes

¿Cómo leo un archivo CSV en Python?

Usa el módulo incorporado csv. csv.reader te da cada fila como una lista de strings; csv.DictReader usa la primera fila como cabeceras y produce cada fila como un dict. Abre el archivo con newline='' para que Python no estropee los finales de línea: with open('data.csv', newline='') as f:.

¿Cómo escribo un archivo CSV en Python?

Empareja csv.writer con un archivo abierto en modo escritura y newline=''. Llama a writer.writerow([...]) por cada fila o writer.writerows([[...], [...]]) para un lote. Para datos basados en dict, usa csv.DictWriter — maneja las cabeceras automáticamente.

¿Debería usar el módulo csv o pandas?

Usa csv para lecturas y escrituras rápidas, archivos que procesas fila a fila y cuando no quieres otra dependencia. Usa pandas cuando necesites filtrar, agrupar o hacer join — o cuando el archivo sea lo bastante grande para que las operaciones vectorizadas importen. Manejan los mismos archivos; la elección va sobre qué haces con los datos después de cargarlos.

¿Por qué mi CSV tiene líneas en blanco entre filas en Windows?

Abriste el archivo sin newline=''. El módulo csv escribe sus propios terminadores de línea; sin ese argumento, Python añade extras en Windows. Abre siempre los archivos CSV con open(path, newline='') tanto para leer como para escribir.

Aprende a programar con Coddy

COMENZAR