7.2.3 Ficheros CSV
El formato CSV (Comma Separated Values) se usa para guardar tablas de datos en texto plano. Es muy habitual para intercambiar información entre Excel, Google Sheets, aplicaciones web y scripts de Python.
Un CSV parece simple, pero tiene reglas importantes (separadores, comillas, saltos de línea) que conviene entender bien.
1️⃣ Qué es un CSV exactamente
Piensa en un CSV como una tabla:
- Cada línea es una fila.
- Cada valor dentro de la línea es una columna.
- Los valores se separan con un delimitador (normalmente
,o;).
Ejemplo:
Nombre,Edad,Ciudad
Ana,20,Sevilla
Luis,22,Malaga
csvUn error común es hacer esto:
linea = '"Apple, Inc.",Cupertino,"1,200.50"'
print(linea.split(","))
Esto rompe datos válidos porque hay comas dentro de comillas.
El módulo csv de Python ya resuelve estos casos correctamente y debe ser la opción por defecto cuando trabajes con CSV reales.
2️⃣ Lectura
🟩 Lectura básica con csv.reader
Antes de usar opciones avanzadas, conviene dominar la lectura más directa de un CSV. Con csv.reader recorremos el archivo fila a fila y obtenemos cada registro como una lista de valores.
import csv
with open("alumnos.csv", "r", encoding="utf-8") as f:
lector = csv.reader(f)
for fila in lector:
print(fila)
open(..., "r")abre el archivo en modo lectura.csv.reader(f)crea un iterador de filas.- Cada
filaes una lista de cadenas.
No todos los CSV usan coma. En muchos entornos (por ejemplo, Excel con configuración regional europea) se usa ;.
lector = csv.reader(f, delimiter=";", quotechar='"')
delimiter: separador de columnas (",",";", etc.).quotechar: carácter que protege textos con separadores internos.
🟦 Lectura con DictReader
Cuando el CSV tiene cabecera, suele ser mejor leer por nombre de columna.
import csv
with open("ventas.csv", "r", encoding="utf-8") as f:
lector = csv.DictReader(f)
for fila in lector:
print(f"Producto: {fila['Producto']} | Total: {fila['Total']}")
- El código es más legible.
- Evitas errores por índices (
fila[2],fila[3], etc.). - Si cambia el orden de columnas, el código suele seguir funcionando.
🟨 Comparativa de funcionamiento (reader vs DictReader)
| Criterio | csv.reader | csv.DictReader |
|---|---|---|
| Tipo de salida por fila | Lista | Diccionario |
| Acceso a datos | Por índice (fila[0]) | Por nombre (fila["Producto"]) |
| Necesita cabecera | No | Sí (o fieldnames) |
| Legibilidad del código | Media | Alta |
| Caso ideal de uso | CSV simple o sin cabecera | CSV tabular con cabeceras |
3️⃣ Escritura con csv.writer y DictWriter
Para guardar datos en CSV también hay dos enfoques principales. Igual que en lectura, puedes trabajar con estructuras simples (listas) o con estructuras más expresivas (diccionarios). Elegir uno u otro depende del tipo de datos y de la claridad que necesites en tu código.
🟩 Opción 1: writer (listas)
csv.writer escribe cada fila como una lista de valores en orden.
import csv
filas = [
["Nombre", "Nivel", "Mundo"],
["Mario", 10, "1-1"],
["Luigi", 12, "2-4"],
]
with open("partida.csv", "w", newline="", encoding="utf-8") as f:
escritor = csv.writer(f)
escritor.writerows(filas)
writerow(...)escribe una sola fila.writerows(...)escribe varias filas de una vez (recibe una lista o iterable de filas).- Si ya tienes todos los datos en una estructura tipo lista de listas,
writerows(...)reduce código repetitivo.
🟦 Opción 2: DictWriter (diccionarios)
csv.DictWriter permite escribir por nombre de campo, lo que aporta más legibilidad y control.
import csv
cabecera = ["Nombre", "Nivel", "Mundo"]
personajes = [
{"Nombre": "Mario", "Nivel": 10, "Mundo": "1-1"},
{"Nombre": "Luigi", "Nivel": 12, "Mundo": "2-4"},
]
with open("partida.csv", "w", newline="", encoding="utf-8") as f:
escritor = csv.DictWriter(f, fieldnames=cabecera)
escritor.writeheader()
escritor.writerows(personajes)
writeheader() y writerows() con DictWriterwriteheader()escribe la primera línea con los nombres de columna definidos enfieldnames.- Es recomendable llamarlo una vez al principio para que el CSV quede autodescriptivo.
writerows(...)escribe todas las filas de diccionarios respetando el orden defieldnames.
🟨 Comparativa de funcionamiento (writer vs DictWriter)
| Criterio | csv.writer | csv.DictWriter |
|---|---|---|
| Tipo de entrada | Lista de listas | Lista de diccionarios |
| Referencia de columnas | Por posición | Por nombre (fieldnames) |
| Cabecera automática | No | Sí (writeheader()) |
| Riesgo por cambio de orden | Más alto | Más bajo |
| Caso ideal de uso | Datos simples y orden fijo | Datos tabulares con esquema claro |
newline=""En Windows, si no usas newline="" al escribir CSV, pueden aparecer líneas en blanco extra.
4️⃣ Ejemplo completo: leer, transformar y guardar
Este ejemplo une todo lo anterior en un flujo único. La idea es que puedas reutilizar este patrón en casi cualquier tarea básica de CSV.
import csv
entradas = []
with open("notas.csv", "r", encoding="utf-8") as f:
lector = csv.DictReader(f)
for fila in lector:
fila["Nota"] = float(fila["Nota"])
fila["Aprobado"] = "SI" if fila["Nota"] >= 5 else "NO"
entradas.append(fila)
with open("notas_resultado.csv", "w", newline="", encoding="utf-8") as f:
campos = ["Alumno", "Nota", "Aprobado"]
escritor = csv.DictWriter(f, fieldnames=campos)
escritor.writeheader()
escritor.writerows(entradas)
Este patrón (leer -> procesar -> escribir) es el flujo más común en tareas de persistencia con CSV.
✅ Buenas prácticas recomendadas
- Usa siempre
with open(...)para cerrar el archivo automáticamente. - Indica
encoding="utf-8"para evitar problemas con caracteres especiales. - Prefiere
DictReader/DictWritercuando trabajes con tablas con cabeceras. - Valida datos antes de convertir tipos (
int,float, etc.) para evitar errores silenciosos.
🧪 Ejercicios prácticos – Operación Mercurio
Tras la auditoría de logs de la unidad anterior, el equipo necesita pasar al siguiente nivel: generar y consumir reportes CSV para el panel de analítica.
Tu misión será leer datos comerciales y de usuarios, validarlos y producir nuevos ficheros CSV listos para explotación.
Dispones de estos ficheros: 👉 Descárgalos aquí
ventas_global.csv-> ventas generales del sistemaventas_europa.csv-> ventas con formato europeo (;y decimal con coma)usuarios_plataforma.csv-> estado de usuarios del sistema
🟢 Fase 1 – Lectura e inspección inicial
🟩 Ejercicio 1 – Lectura base de ventas (ventas_global.csv)
Lee el archivo con csv.reader y muestra:
- Número total de filas de datos (sin cabecera).
- Primera venta registrada.
- Última venta registrada.
Objetivo: practicar lectura secuencial con listas.
🟦 Ejercicio 2 – Lectura con formato europeo (ventas_europa.csv)
Procesa el fichero usando:
delimiter=";"- Conversión de
PrecioUnitariode texto con coma decimal afloatreal.
Muestra por pantalla el total de facturación europea.
Objetivo: manejar dialectos y transformación de tipos en CSV.
🟡 Fase 2 – Lectura estructurada y validación
🟨 Ejercicio 3 – Facturación por canal con DictReader (ventas_global.csv)
Usando csv.DictReader, calcula la facturación total por canal (Web, Tienda, App).
Condiciones:
- Convierte
Unidadesaint. - Convierte
PrecioUnitarioafloat. - Acumula en un diccionario, por ejemplo:
{"Web": 1200.0, "Tienda": 800.0, "App": 500.0}.
Objetivo: trabajar con lectura por nombre de campo.
🟧 Ejercicio 4 – Detección de registros inconsistentes (usuarios_plataforma.csv)
Detecta y cuenta registros problemáticos:
- Usuario marcado como
activo=Trueconultimo_accesovacío. - Filas sin
ido sinnombre.
Muestra:
- Total de registros inconsistentes.
- 2 ejemplos de líneas problemáticas.
Objetivo: validar calidad de datos antes de escribir nuevos CSV.
🔵 Fase 3 – Escritura de reportes CSV
🟥 Ejercicio 5 – Resumen por categoría con writer (resumen_categorias.csv)
Genera un nuevo CSV con esta estructura:
Categoria,UnidadesTotales,FacturacionTotal
Condiciones:
- Usa
csv.writer. - Escribe primero la cabecera con
writerow(...). - Escribe el resto con
writerows(...).
Objetivo: practicar escritura basada en listas y control manual de columnas.
🟫 Ejercicio 6 – Exportación de usuarios activos con DictWriter (usuarios_activos.csv)
Crea un fichero con solo usuarios válidos y activos (activo=True y ultimo_acceso no vacío).
Columnas obligatorias:
idnombrerolultimo_acceso
Condiciones:
- Usa
csv.DictWriter. - Define
fieldnames. - Escribe cabecera con
writeheader().
Objetivo: consolidar escritura por diccionarios con esquema fijo.
🟪 Ejercicio 7 – Comparativa de salida (writer vs DictWriter)
Genera dos archivos con el mismo contenido (top 3 productos por unidades vendidas):
top_productos_writer.csv(concsv.writer)top_productos_dictwriter.csv(concsv.DictWriter)
Después, verifica que:
- Tienen la misma cantidad de filas.
- Contienen la misma información (aunque cambie el enfoque de escritura).
Objetivo: entender en práctica cuándo usar cada herramienta.
🔴 Fase Final – Entrega del informe
🟪 Ejercicio 8 – Informe de cierre (informe_csv.txt)
Genera un informe final en texto plano que incluya:
- Total de ventas procesadas en
ventas_global.csv. - Facturación total global.
- Facturación total europea.
- Número de registros inconsistentes de usuarios.
- Número de usuarios activos exportados.
Formato sugerido:
Ventas globales procesadas: X
Facturación global: XXXX.XX
Facturación europea: XXXX.XX
Registros inconsistentes: X
Usuarios activos exportados: X