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=""aopen. 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 aint(...). 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:
(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=""aopenal leer o escribir CSVs. - Usa
DictReader/DictWritercuando 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.