Cómo leer archivos gigantes con Python sin bloquear el sistema

Publicado el: 11/07/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

    Herança múltipla em Python sem causar problemas no código
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    Herencia múltiple en Python: MRO, super() y mixins

    Aprende herencia múltiple en Python con MRO, super(), mixins, problema del diamante, inicializadores cooperativos, composición y pruebas.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Criando instalador EXE com ícone personalizado em Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    Cómo crear un ejecutable EXE con icono personalizado en Python

    Crea un EXE de Python con PyInstaller, icono ICO, onefile, windowed, archivos de datos, SPEC, rutas seguras, pruebas y distribución.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Uso do super em Python para resolver problemas de herança
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    Cómo usar super() en Python sin errores de herencia

    Aprende a usar super() en Python con __init__, MRO, herencia múltiple, mixins, argumentos cooperativos, pruebas y composición.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Uso de multiprocessing em Python para acelerar scripts
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    Multiprocessing en Python: usa varios núcleos correctamente

    Aprende multiprocessing en Python con Process, Pool, Queue, memoria compartida, ProcessPoolExecutor, benchmarks y buenas prácticas.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Criação de geradores eficientes usando yield em Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    yield en Python: crea generadores eficientes

    Aprende yield en Python para crear generadores, procesar archivos grandes, construir pipelines, usar yield from y reducir el consumo de

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    Decoradores en Python: guía práctica y ejemplos

    Aprende decoradores en Python con wrappers, argumentos, functools.wraps, parámetros, validación, rendimiento y buenas prácticas.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026