Archivos grandes en Python: streaming y chunks

Actualizado el: 21/08/2026
Tempo de leitura: 5 minutos
Leitura de arquivos grandes em Python sem travar o sistema

Leer archivos de varios gigabytes con Python puede bloquear un programa si se intenta cargar todo el contenido en memoria. La solución consiste en procesar los datos de forma incremental: línea por línea, por bloques o mediante iteradores. Este enfoque permite trabajar con registros, CSV, JSONL y archivos comprimidos incluso en equipos con recursos limitados.

Antes de continuar, puedes ampliar conceptos con las guías sobre archivos de texto en Python, generadores con yield, manejo de excepciones, logging y archivos CSV. Como referencias externas, consulta la documentación oficial de open() y la documentación del módulo io.

Por qué leer todo el archivo es un problema

El método read() sin tamaño intenta devolver todo el contenido. Si un archivo pesa 8 GB, el programa puede necesitar todavía más memoria por la representación interna de strings, estructuras auxiliares y copias temporales. El sistema operativo comienza a intercambiar memoria con el disco, el proceso se vuelve lento y finalmente puede aparecer MemoryError o un cierre forzado.

Lectura línea por línea

La forma más sencilla y segura para archivos de texto es iterar directamente sobre el objeto abierto. Python mantiene un búfer interno y entrega una línea cada vez.

from pathlib import Path

ruta = Path("servidor.log")

with ruta.open("r", encoding="utf-8") as archivo:
    for numero, linea in enumerate(archivo, start=1):
        if "ERROR" in linea:
            print(numero, linea.rstrip())

Este patrón mantiene el consumo de memoria casi constante. También garantiza el cierre del descriptor gracias a la sentencia with.

Procesar por bloques de bytes

Algunos archivos no están organizados por líneas o contienen registros muy largos. En esos casos, utiliza un tamaño fijo y repite la lectura hasta recibir una cadena vacía.

def leer_bloques(ruta, tamano=1024 * 1024):
    with open(ruta, "rb") as archivo:
        while bloque := archivo.read(tamano):
            yield bloque

for bloque in leer_bloques("datos.bin"):
    procesar(bloque)

Un bloque de un megabyte suele ser un punto de partida razonable, pero conviene medir. Bloques demasiado pequeños aumentan llamadas al sistema; bloques enormes vuelven a elevar el uso de memoria.

Crear un generador de registros

Separar lectura y transformación facilita reutilizar el flujo. Un generador puede limpiar cada línea y producir únicamente registros válidos.

import json

def registros_jsonl(ruta):
    with open(ruta, encoding="utf-8") as archivo:
        for numero, linea in enumerate(archivo, 1):
            linea = linea.strip()
            if not linea:
                continue
            try:
                yield json.loads(linea)
            except json.JSONDecodeError as error:
                print(f"Línea {numero} inválida: {error}")

El consumidor decide si filtra, agrega, guarda o envía los objetos. En ningún momento se conserva todo el conjunto.

CSV grandes con el módulo csv

csv.DictReader también funciona como iterador. No necesitas convertirlo a lista, porque eso eliminaría la ventaja del procesamiento incremental.

import csv

with open("ventas.csv", newline="", encoding="utf-8") as archivo:
    lector = csv.DictReader(archivo)
    total = 0
    for fila in lector:
        total += int(fila["cantidad"])

print(total)

Valida columnas y conversiones. Una fila defectuosa no debería destruir horas de procesamiento; registra el número de línea y decide si omitirla o detener el trabajo.

Pandas con chunksize

Cuando necesitas operaciones de Pandas, utiliza chunksize. Cada fragmento es un DataFrame independiente que puede limpiarse y agregarse.

import pandas as pd

totales = {}

for fragmento in pd.read_csv("ventas.csv", chunksize=100_000):
    resumen = fragmento.groupby("categoria")["importe"].sum()
    for categoria, valor in resumen.items():
        totales[categoria] = totales.get(categoria, 0) + valor

El tamaño ideal depende del número de columnas, tipos y memoria disponible. Observa el proceso con datos reales en lugar de escoger un valor arbitrario.

Archivos comprimidos sin extracción completa

Los módulos gzip, bz2 y lzma exponen interfaces similares a open(). Puedes recorrer un archivo comprimido sin crear una copia completa en disco.

import gzip

with gzip.open("eventos.jsonl.gz", "rt", encoding="utf-8") as archivo:
    for linea in archivo:
        procesar(linea)

La descompresión consume CPU, pero ahorra espacio y operaciones de entrada y salida. Debes limitar tamaños cuando el archivo procede de una fuente no confiable.

Codificación y errores de texto

Especifica siempre una codificación. UTF-8 es la opción habitual, pero archivos antiguos pueden usar Windows-1252 o Latin-1. No utilices errors="ignore" automáticamente, porque puede eliminar información silenciosamente. Primero identifica el origen, prueba una muestra y registra cualquier sustitución.

Reanudar un proceso interrumpido

Para trabajos largos, guarda un punto de control: número de línea, desplazamiento de bytes o identificador del último registro confirmado. Al reiniciar, abre el archivo, avanza de forma controlada y continúa. El punto debe actualizarse después de guardar correctamente el resultado, no antes, para evitar pérdida de datos.

Escritura incremental

El resultado tampoco debe acumularse en una lista gigantesca. Escribe cada lote en CSV, base de datos o archivo temporal. Si la salida final es crítica, escribe en un nombre temporal, sincroniza, valida y reemplaza el destino al terminar. Así un fallo no deja un archivo aparentemente completo pero corrupto.

Evitar operaciones costosas dentro del bucle

Compila expresiones regulares antes de recorrer millones de líneas, prepara conexiones y constantes fuera del bucle y evita imprimir cada registro. El terminal puede convertirse en el cuello de botella. Para progreso, informa cada diez mil o cien mil elementos mediante logging.

Paralelismo con cuidado

Dividir un archivo por bytes puede cortar caracteres o registros. Para formatos basados en líneas, cada trabajador debe comenzar en un límite válido. Antes de usar procesos paralelos, mide una versión secuencial. Muchas tareas están limitadas por el disco y no mejoran al añadir trabajadores; incluso pueden empeorar por competencia de entrada y salida.

Pruebas recomendadas

Prueba un archivo vacío, una sola línea, caracteres Unicode, líneas enormes, registros inválidos, interrupciones y falta de espacio. Compara el total obtenido con un conjunto pequeño conocido. Mide memoria y tiempo, porque un programa correcto pero incapaz de terminar no es una solución completa.

Errores frecuentes

Los errores más comunes son usar read() sin límite, convertir iteradores a lista, acumular resultados, ignorar codificación, imprimir millones de veces y no cerrar archivos. También es peligroso confiar en el tamaño comprimido: un archivo pequeño puede expandirse de forma desproporcionada.

Conclusión

La clave para leer archivos gigantes es mantener un flujo constante y limitado. Itera línea por línea, usa bloques cuando sea necesario, crea generadores, procesa CSV por fragmentos y escribe resultados incrementalmente. Añade puntos de control, logs y pruebas con datos problemáticos. Con esta arquitectura, el tamaño del archivo deja de estar directamente limitado por la memoria RAM.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Close-up view of a computer screen displaying code in a software development environment.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    ftplib en Python: FTP y FTPS seguros

    Aprende ftplib en Python para listar, descargar y subir archivos por FTP o FTPS con TLS, timeouts, límites, reanudación y

    Ler mais

    Tempo de leitura: 5 minutos
    21/08/2026
    Rack de servidores que representa un endpoint creado con xmlrpc.server en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    xmlrpc.server: crea servidores XML-RPC

    Aprende xmlrpc.server en Python para crear servidores XML-RPC, registrar funciones, limitar métodos y rutas y evitar exposición insegura.

    Ler mais

    Tempo de leitura: 6 minutos
    21/08/2026
    Código de error sobre datos binarios que representa fallos manejados con urllib.error en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    urllib.error en Python: maneja errores HTTP

    Aprende urllib.error en Python para manejar URLError, HTTPError, descargas incompletas, retries selectivos y diagnósticos de red claros.

    Ler mais

    Tempo de leitura: 5 minutos
    21/08/2026
    Teclas con la palabra HTML que representan entidades HTML en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    html.entities: convierte entidades HTML

    Aprende html.entities en Python para consultar entidades HTML, convertir nombres y code points y no confundir decodificación con sanitización.

    Ler mais

    Tempo de leitura: 7 minutos
    21/08/2026
    Carpeta con archivos que representa tipos MIME identificados con mimetypes en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    mimetypes: detecta tipos MIME de archivos

    Aprende mimetypes en Python para identificar tipos de archivo, validar cargas y definir Content-Type con más seguridad.

    Ler mais

    Tempo de leitura: 6 minutos
    20/08/2026
    Código HTML en una pantalla que representa análisis con html.parser en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    html.parser en Python: analiza HTML

    Aprende html.parser en Python para extraer texto, enlaces y metadatos, procesar HTML por bloques y no confundir parsing con sanitización.

    Ler mais

    Tempo de leitura: 4 minutos
    20/08/2026