▷ Leer y escribir CSV en Python — Guía práctica con csv y pandas 2026

Leer y escribir CSV en Python — Guía práctica con csv y pandas

Si trabajas con datos en Python, antes o después te toca pelearte con un CSV. Y aunque suene a tema básico, te garantizo que el 90% de los problemas con CSV no vienen de Python — vienen del propio fichero: encoding raro, separador con punto y coma en vez de coma, comillas mal puestas, valores con saltos de línea dentro…

Esta entrada es la guía práctica para leer y escribir CSV en Python sin sufrir. Con la librería estándar csv (cuando quieres control total) y con pandas (cuando quieres velocidad y no reinventar la rueda). Y con la lista de los problemas típicos para que sepas qué buscar cuando algo no funciona.

Qué es exactamente un CSV

CSV (Comma-Separated Values) es un formato de texto plano para tablas. Cada línea es una fila; cada columna está separada por un delimitador, normalmente la coma. Ejemplo:

nombre,edad,ciudad
Ana,30,Madrid
Pedro,25,Barcelona
Luis,40,Valencia

Suena simple. No lo es. En la práctica te encuentras:

  • Comas dentro de un valor: "Ramírez, Oscar",35,Madrid (van entre comillas)
  • Separador ; en vez de , (típico de Excel en español)
  • Encoding diferente: UTF-8, latin-1, cp1252 (Windows)
  • Saltos de línea dentro de un campo
  • Cabecera o no
  • Comillas mezcladas

Por eso Python tiene una librería entera dedicada al tema (csv) y pandas añade encima muchísima inteligencia.

Leer un CSV con la librería estándar (csv)

Esta es la opción de la librería estándar: viene con Python, no instalas nada.

Caso simple: csv.reader

import csv

with open("usuarios.csv", encoding="utf-8") as archivo:
    lector = csv.reader(archivo)
    for fila in lector:
        print(fila)

Salida:

['nombre', 'edad', 'ciudad']
['Ana', '30', 'Madrid']
['Pedro', '25', 'Barcelona']
['Luis', '40', 'Valencia']

Cada fila es una lista de strings. Atención: '30' no es un número — es un string. Si quieres usarlo como entero, conviértelo tú con int(fila[1]).

Saltar la cabecera

Lo más típico: la primera fila son los nombres de columna y no la quieres tratar como dato.

import csv

with open("usuarios.csv", encoding="utf-8") as archivo:
    lector = csv.reader(archivo)
    cabecera = next(lector)              # ← consume la primera fila
    print("Columnas:", cabecera)

    for fila in lector:
        nombre, edad, ciudad = fila      # unpacking
        print(f"{nombre} ({int(edad)}) vive en {ciudad}")

Trabajar con diccionarios: csv.DictReader

Mucho más cómodo cuando hay varias columnas:

import csv

with open("usuarios.csv", encoding="utf-8") as archivo:
    lector = csv.DictReader(archivo)
    for fila in lector:
        print(f"{fila['nombre']} vive en {fila['ciudad']}")

DictReader lee la primera fila como cabecera automáticamente y te da cada fila como un dict. Más legible, especialmente si el CSV tiene 10+ columnas.

Separador ; o tabulador

Cuando el CSV no usa coma:

# Con punto y coma (típico Excel español)
csv.reader(archivo, delimiter=";")

# Con tabulador (TSV)
csv.reader(archivo, delimiter="\t")

💡 Tip-friki: si no sabes qué delimitador trae el fichero, csv.Sniffer lo detecta solo:
python
dialecto = csv.Sniffer().sniff(archivo.read(1024))
archivo.seek(0)
lector = csv.reader(archivo, dialect=dialecto)

Escribir un CSV con csv

Idem, pero al revés. Punto importante: en Windows y para evitar líneas en blanco entre filas, usa newline="" al abrir el fichero.

Caso simple: csv.writer

import csv

filas = [
    ["nombre", "edad", "ciudad"],
    ["Ana", 30, "Madrid"],
    ["Pedro", 25, "Barcelona"],
    ["Luis", 40, "Valencia"],
]

with open("salida.csv", "w", encoding="utf-8", newline="") as archivo:
    escritor = csv.writer(archivo)
    escritor.writerows(filas)

writerows escribe varias filas. Para una sola: escritor.writerow(["Ana", 30, "Madrid"]).

Con diccionarios: csv.DictWriter

import csv

usuarios = [
    {"nombre": "Ana", "edad": 30, "ciudad": "Madrid"},
    {"nombre": "Pedro", "edad": 25, "ciudad": "Barcelona"},
    {"nombre": "Luis", "edad": 40, "ciudad": "Valencia"},
]

with open("salida.csv", "w", encoding="utf-8", newline="") as archivo:
    columnas = ["nombre", "edad", "ciudad"]
    escritor = csv.DictWriter(archivo, fieldnames=columnas)
    escritor.writeheader()              # escribe la cabecera
    escritor.writerows(usuarios)

Si en algún diccionario falta una clave, DictWriter la deja vacía. Si sobra, da error (a menos que pases extrasaction="ignore").

📥 Llévate el cheatsheet de Python (gratis)

PDF de 6 páginas con lo esencial: tipos, condicionales, bucles, estructuras de datos, funciones y los errores que más vas a cometer. Para tener al lado mientras programas.

Sin spam. Te apuntas a la lista, descargas el cheatsheet y recibes contenido de Python cada semana.

Y ahora con pandas (cuando hay datos serios)

pandas es la librería estándar de facto para análisis de datos en Python. Para CSV de más de unas pocas filas, es lo que vas a querer usar.

pip install pandas

Leer

import pandas as pd

df = pd.read_csv("usuarios.csv")
print(df)

Salida:

   nombre  edad     ciudad
0     Ana    30     Madrid
1   Pedro    25  Barcelona
2    Luis    40   Valencia

pd.read_csv ya hace por ti:

  • Lee la cabecera automáticamente.
  • Convierte los tipos: edad ya es int, no string.
  • Devuelve un DataFrame (la estructura tabular de pandas) sobre la que puedes filtrar, agrupar, ordenar y todo lo que se te ocurra.

Argumentos típicos de read_csv

pd.read_csv(
    "datos.csv",
    sep=";",                  # delimitador (por defecto ",")
    encoding="utf-8",         # o "latin-1", "cp1252"
    header=0,                 # qué fila es la cabecera (None si no hay)
    names=["a", "b", "c"],    # nombres de columna manuales
    skiprows=2,               # saltar las primeras N filas
    nrows=1000,               # leer solo las primeras N filas
    na_values=["NA", "-"],    # qué strings tratar como NaN
    parse_dates=["fecha"],    # columnas que son fechas
    dtype={"id": str},        # forzar tipo de una columna
)

Los dos argumentos que vas a tocar el 80% del tiempo: sep y encoding. Si tu CSV viene de Excel español, casi seguro: sep=";" y encoding="latin-1" o "cp1252".

Operaciones rápidas en el DataFrame

import pandas as pd

df = pd.read_csv("usuarios.csv")

print(df.head())                          # primeras 5 filas
print(df.shape)                           # (filas, columnas)
print(df.dtypes)                          # tipos de cada columna
print(df["edad"].mean())                  # media de la columna edad
print(df[df["edad"] > 28])                # filtrar filas
print(df.groupby("ciudad").size())        # contar por ciudad
print(df.sort_values("edad"))             # ordenar por edad

Todo eso en una línea cada cosa. Si lo hicieras con la librería csv puro, son bucles + diccionarios manuales. Por eso pandas existe.

Escribir

df.to_csv("salida.csv", index=False, encoding="utf-8")

index=False es crítico — si no lo pones, pandas escribe una columna extra con el índice (0, 1, 2…) que casi nunca quieres.

Encoding: el problema número 1 con CSV

Si abres un CSV español y ves cosas como Mar�a, Andalu��a, o errores tipo UnicodeDecodeErrores encoding. Tu fichero no está en UTF-8 (lo más común hoy), sino en una codificación más antigua.

Probables sospechosos por orden de probabilidad:

# 1. UTF-8 (estándar moderno)
encoding="utf-8"

# 2. UTF-8 con BOM (Excel a veces añade un marker)
encoding="utf-8-sig"

# 3. Latin-1 (ISO-8859-1, español clásico)
encoding="latin-1"

# 4. Windows-1252 (Excel en Windows español)
encoding="cp1252"

Si no sabes cuál es, prueba en este orden. Y si te aburre adivinar:

import chardet  # pip install chardet

with open("misterio.csv", "rb") as f:
    detect = chardet.detect(f.read(10000))
    print(detect)   # {'encoding': 'utf-8', 'confidence': 0.99, ...}

Casos reales de uso

1. Filtrar un CSV grande y guardar el resultado

import pandas as pd

df = pd.read_csv("ventas.csv")
ventas_2024 = df[df["año"] == 2024]
ventas_2024.to_csv("ventas_2024.csv", index=False)

2. Combinar dos CSV con la misma estructura

import pandas as pd

df1 = pd.read_csv("enero.csv")
df2 = pd.read_csv("febrero.csv")
combinado = pd.concat([df1, df2], ignore_index=True)
combinado.to_csv("ene_feb.csv", index=False)

3. Limpiar un CSV: quitar duplicados, normalizar texto

import pandas as pd

df = pd.read_csv("usuarios.csv")
df["nombre"] = df["nombre"].str.strip().str.title()
df = df.drop_duplicates(subset=["email"])
df.to_csv("usuarios_limpios.csv", index=False)

4. Procesar un CSV gigante por trozos (cuando no cabe en memoria)

import pandas as pd

for chunk in pd.read_csv("gigante.csv", chunksize=100_000):
    procesar(chunk)

chunksize te devuelve un iterador de DataFrames de N filas cada uno. Útil para CSVs de 1 GB+ que no entran en RAM.

csv vs pandas: ¿cuál elijo?

SituaciónMejor opción
Script ligero, pocos requisitos, sin dependenciascsv
Procesar CSV de pocas líneas en memoriacsv
Análisis de datos, filtrado, agrupadopandas
Archivos grandes con muchas columnaspandas
Leer una fila a la vez en streamingcsv
Joins entre varios CSVpandas
Lo voy a meter en una base de datospandas (lee CSV, escribe a SQL en una línea)

Regla mental: si vas a hacer cualquier análisis o transformación seria, pandas. Si solo lees fila a fila para meterlas en otro sitio, csv.

Errores típicos

# 1. No usar newline="" al escribir en Windows
# → Líneas en blanco entre filas

# 2. Olvidar index=False con pandas
df.to_csv("x.csv")           # MAL: añade columna 0,1,2,3,...
df.to_csv("x.csv", index=False)  # BIEN

# 3. Confundir encoding al leer un CSV español de Excel
pd.read_csv("ventas.csv")                          # explota
pd.read_csv("ventas.csv", encoding="latin-1", sep=";")  # bien

# 4. Comillas dentro de campos sin escapar
# Si tu CSV tiene texto con comas y mal-escapado, csv.reader puede leer mal.
# Solución: pandas con sep=",", quotechar='"', engine="python".

¿Te ha valido esto?

Si te ha resultado útil, llévate el cheatsheet de Python en PDF — 6 páginas con tipos, condicionales, bucles, estructuras de datos, funciones y los errores típicos. Para tener al lado mientras programas. Gratis.

Sin spam. Email + cheatsheet + un correo por semana con tutoriales nuevos.

Tu siguiente paso

Si has llegado aquí, ya manejas CSV en Python mejor que la mayoría de la gente que se pelea con datos a diario. La clave es saber cuándo usar cada herramienta: csv para scripts pequeños y autosuficientes, pandas cuando hay que hacer algo más serio.

En El Pythonista te enseño a manejar archivos, datos y proyectos reales desde la base. Cuando dominas estos fundamentos, todo lo demás (APIs, web, dashboards, IA) viene rodado.

Un abrazo,
Oscar

¿Quieres aprender Python en orden, no a saltos?

Esto que has leído es solo una pieza. En El Pythonista lo verás todo encadenado: 11 módulos, 37+ horas de vídeo, 734 actividades y un proyecto real (MovieTracker) que crece contigo desde la primera variable hasta el deploy a producción.

Ver el curso completo →

37+ horas · 734 actividades · Proyecto real · Acceso de por vida · 14 días de garantía

Compartir