W3docs

Archivos CSV en Python

Aprende a leer y escribir archivos CSV en Python con el módulo csv: csv.reader, csv.writer, DictReader y DictWriter con ejemplos prácticos.

CSV (Valores Separados por Comas) es uno de los formatos más comunes para intercambiar datos tabulares: cualquier hoja de cálculo, base de datos y herramienta de ciencia de datos puede leerlo y escribirlo. El módulo integrado csv de Python maneja automáticamente las partes más complicadas: entrecomillar campos que contienen comas, eliminar las peculiaridades de los saltos de línea entre sistemas operativos y mapear filas a diccionarios. No necesitas instalar nada; csv viene incluido en toda instalación de Python.

Este capítulo cubre la lectura de archivos CSV, la escritura de archivos CSV, el trabajo con DictReader y DictWriter, el manejo de delimitadores personalizados y los errores comunes que debes evitar.

¿Qué es un Archivo CSV?

Un archivo CSV es un archivo de texto plano donde cada línea representa una fila de datos y cada campo dentro de una fila está separado por un delimitador, generalmente una coma. Aquí hay un ejemplo mínimo:

name,age,city
Alice,30,New York
Bob,25,London

La primera fila es típicamente un encabezado que nombra cada columna. Las filas siguientes contienen los datos reales. Si el valor de un campo contiene una coma, el campo se envuelve en comillas dobles:

name,bio
Alice,"Engineer, New York"

El módulo csv maneja este entrecomillado de forma transparente, por lo que no necesitas analizarlo manualmente.

Leer Archivos CSV con csv.reader

csv.reader convierte un archivo abierto (o cualquier iterable de strings) en un iterador que devuelve cada fila como una lista de Python.

Patrón básico — leer un archivo CSV fila por fila

import csv

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

El argumento newline="" es importante. Sin él, la traducción universal de saltos de línea de Python puede insertar filas en blanco adicionales en Windows porque el módulo csv realiza su propio manejo de saltos de línea internamente.

Suponiendo que people.csv contiene los datos del ejemplo anterior, la salida es:

['name', 'age', 'city']
['Alice', '30', 'New York']
['Bob', '25', 'London']

Observa que todos los valores, incluido el número 30, se devuelven como strings. El módulo csv no infiere tipos de datos; conviértelos tú mismo cuando sea necesario.

Saltar la Fila de Encabezado

Cuando solo quieres las filas de datos y no el encabezado, llama a next() en el lector una vez para consumir la primera línea:

Saltar la fila de encabezado con next()

import csv

with open("people.csv", newline="") as f:
    reader = csv.reader(f)
    header = next(reader)          # consume and store the header
    print("Columns:", header)
    for row in reader:             # only data rows remain
        name, age, city = row
        print(f"{name} is {age} years old and lives in {city}.")

Salida:

Columns: ['name', 'age', 'city']
Alice is 30 years old and lives in New York.
Bob is 25 years old and lives in London.

Cargar Todas las Filas en una Lista

Si necesitas el archivo completo en memoria de una vez, pasa el lector a list():

import csv

with open("people.csv", newline="") as f:
    reader = csv.reader(f)
    rows = list(reader)

print(rows[0])   # header row
print(rows[1])   # first data row

Salida:

['name', 'age', 'city']
['Alice', '30', 'New York']

Escribir Archivos CSV con csv.writer

csv.writer escribe filas en cualquier objeto similar a un archivo, entrecomillando automáticamente los campos que contienen el delimitador, comillas dobles o caracteres de salto de línea.

Escribir filas en un nuevo archivo CSV

import csv

rows = [
    ["product", "price", "quantity"],
    ["Apple", 1.2, 50],
    ["Banana", 0.5, 100],
    ["Cherry", 3.0, 30],
]

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

Después de ejecutar esto, inventory.csv contiene:

product,price,quantity
Apple,1.2,50
Banana,0.5,100
Cherry,3.0,30

Usa writer.writerow(row) para escribir una sola fila, o writer.writerows(rows) para escribir muchas a la vez. Ambos aceptan cualquier iterable.

Por Qué newline="" Importa al Escribir

En Windows, Python abre los archivos de texto en un modo que traduce \n a \r\n. El módulo csv también escribe terminaciones de línea \r\n por defecto. Juntos producen \r\r\n, lo que genera una línea en blanco entre cada fila cuando el archivo se abre en otro programa. Pasar newline="" suprime la traducción adicional y permite que csv administre los finales de línea por sí solo.

Leer Archivos CSV con csv.DictReader

DictReader mapea cada fila a un OrderedDict (o un dict simple en Python 3.8+) con claves basadas en los nombres de las columnas del encabezado. Este es el enfoque preferido cuando las columnas tienen nombres significativos y quieres acceder a ellas por nombre en lugar de por índice.

Leer un archivo CSV como una secuencia de diccionarios

import csv

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

Salida:

Alice — New York
Bob — London

DictReader lee la primera fila automáticamente como el encabezado. Puedes anular esto pasando un argumento fieldnames:

import csv

# File has no header; provide field names explicitly
with open("data_no_header.csv", newline="") as f:
    reader = csv.DictReader(f, fieldnames=["name", "age", "city"])
    for row in reader:
        print(row)

El atributo reader.fieldnames siempre contiene la lista de nombres de columnas en uso, lo que es útil para la inspección antes de procesar las filas.

Escribir Archivos CSV con csv.DictWriter

DictWriter es la contraparte de DictReader. Proporcionas los nombres de las columnas de antemano y luego escribes diccionarios: el escritor mapea cada clave a la columna correcta.

Escribir una lista de diccionarios en un archivo CSV

import csv

people = [
    {"name": "Alice", "age": 30, "city": "New York"},
    {"name": "Bob", "age": 25, "city": "London"},
]

fieldnames = ["name", "age", "city"]

with open("people_out.csv", "w", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()          # writes the column-name row
    writer.writerows(people)

El archivo resultante:

name,age,city
Alice,30,New York
Bob,25,London

writeheader() usa la lista fieldnames que proporcionaste en la construcción. Llámalo una vez antes de cualquier llamada a writerow().

Manejo de Claves Extra o Faltantes

Por defecto, DictWriter lanza un ValueError si un diccionario contiene una clave que no está en fieldnames. Puedes cambiar este comportamiento con el parámetro extrasaction:

writer = csv.DictWriter(f, fieldnames=fieldnames, extrasaction="ignore")

Por el contrario, si a un diccionario le falta una clave, el escritor escribe un string vacío para ese campo a menos que proporciones un valor predeterminado restval:

writer = csv.DictWriter(f, fieldnames=fieldnames, restval="N/A")

Delimitadores y Entrecomillado Personalizados

Los archivos CSV del mundo real no siempre usan comas como delimitador. Los archivos de valores separados por tabulaciones (TSV) y los archivos delimitados por tuberías son comunes. Usa el parámetro delimiter para manejarlos:

Leer un archivo separado por tabulaciones

import csv

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

Escribir un archivo delimitado por tuberías

import csv

with open("output.psv", "w", newline="") as f:
    writer = csv.writer(f, delimiter="|")
    writer.writerow(["id", "name", "score"])
    writer.writerow([1, "Alice", 98])
    writer.writerow([2, "Bob", 87])

Archivo de salida:

id|name|score
1|Alice|98
2|Bob|87

Constantes de Entrecomillado

El parámetro quoting controla qué campos se entrecomillan en la salida:

ConstanteValorComportamiento
csv.QUOTE_MINIMAL0Entrecomillar solo los campos que contienen el delimitador, el carácter de comillas o un salto de línea (predeterminado)
csv.QUOTE_ALL1Entrecomillar todos los campos
csv.QUOTE_NONNUMERIC2Entrecomillar todos los campos no numéricos; el lector convierte los campos no entrecomillados a float
csv.QUOTE_NONE3No entrecomillar nunca; lanzar error si el delimitador aparece en un campo

Forzar que todos los campos sean entrecomillados

import csv, io

output = io.StringIO()
writer = csv.writer(output, quoting=csv.QUOTE_ALL)
writer.writerow(["name", "bio"])
writer.writerow(["Alice", "Engineer, New York"])
print(output.getvalue())

Salida:

"name","bio"
"Alice","Engineer, New York"

Usar io.StringIO para CSV en Memoria

Cuando no necesitas acceder al sistema de archivos, por ejemplo en pruebas o al procesar datos CSV recibidos desde una API, usa io.StringIO como objeto similar a un archivo:

Analizar CSV desde un string

import csv
import io

raw = "name,score\nAlice,95\nBob,87\n"

reader = csv.DictReader(io.StringIO(raw))
for row in reader:
    print(row["name"], "scored", row["score"])

Salida:

Alice scored 95
Bob scored 87

Errores Comunes

Todos los Valores Son Strings

csv.reader y DictReader siempre devuelven strings. Convierte los valores de forma explícita:

age = int(row["age"])
price = float(row["price"])

Problemas de Codificación

Abre los archivos con la codificación correcta para evitar UnicodeDecodeError. UTF-8 es la codificación más común para los archivos CSV modernos, pero los archivos exportados desde Excel pueden usar latin-1 o cp1252:

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

Filas en Blanco

Si tu archivo CSV contiene líneas en blanco entre filas de datos, csv.reader devuelve listas vacías [] para ellas. Fíltralas:

import csv

with open("data.csv", newline="") as f:
    reader = csv.reader(f)
    for row in reader:
        if not row:        # skip blank lines
            continue
        print(row)

Manejo de Errores

Envuelve las operaciones de archivos en un bloque try/except para manejar archivos no encontrados y errores de permisos de forma elegante:

import csv

try:
    with open("data.csv", newline="") as f:
        reader = csv.reader(f)
        for row in reader:
            print(row)
except FileNotFoundError:
    print("Error: data.csv was not found.")
except PermissionError:
    print("Error: no permission to read data.csv.")

csv vs Pandas para Archivos Grandes

El módulo csv es ideal para:

  • Archivos pequeños a medianos (hasta unos pocos cientos de MB)
  • Scripts que no tienen Pandas instalado
  • Situaciones donde necesitas un control detallado sobre la lectura y escritura

Para conjuntos de datos grandes, filtrado complejo u operaciones de agregación, la librería de terceros pandas proporciona pd.read_csv() y DataFrame.to_csv(), que son significativamente más rápidos y con más características.

Integrando Todo

El siguiente ejemplo lee un archivo CSV, filtra filas según una condición y escribe los resultados filtrados en un nuevo archivo:

Filtrar filas y escribir un nuevo archivo CSV

import csv

input_file = "inventory.csv"
output_file = "expensive.csv"

with open(input_file, newline="") as infile, \
     open(output_file, "w", newline="") as outfile:

    reader = csv.DictReader(infile)
    writer = csv.DictWriter(outfile, fieldnames=reader.fieldnames)

    writer.writeheader()
    for row in reader:
        if float(row["price"]) >= 1.0:
            writer.writerow(row)

print(f"Filtered rows written to {output_file}.")

Este patrón — abrir ambos archivos en el mismo bloque with, transmitir filas del lector al escritor — maneja archivos de cualquier tamaño sin cargar todo en memoria a la vez.

Capítulos Relacionados

Práctica

Práctica
Which csv module class maps each CSV row to a dictionary keyed by column names?
Which csv module class maps each CSV row to a dictionary keyed by column names?
Was this page helpful?