tqdm en Python: barras de progreso para scripts

Actualizado el: 11/07/2026
Tempo de leitura: 3 minutos
Barra de progresso com tqdm para scripts Python

Los scripts que tardan varios segundos o minutos deben informar que el trabajo continúa. Sin una señal visible, una descarga, conversión de archivos o limpieza de datos puede parecer bloqueada aunque funcione correctamente. La biblioteca tqdm en Python añade barras de progreso a los bucles con muy poco código.

En esta guía aprenderás a instalar tqdm, envolver iterables, mostrar descripciones y unidades, actualizar el progreso manualmente, trabajar con archivos, pandas, descargas, barras anidadas y ejecuciones no interactivas.

Qué es tqdm

tqdm recibe un iterable y muestra elementos completados, total, tiempo transcurrido, velocidad y tiempo estimado restante cuando conoce el tamaño total.

Consulta la documentación oficial de tqdm y su página en PyPI para revisar opciones y versiones.

Instalar tqdm

python -m pip install tqdm

Comprueba la instalación:

python -c "import tqdm; print(tqdm.__version__)"

Primera barra de progreso

import time
from tqdm import tqdm

for elemento in tqdm(range(100)):
    time.sleep(0.03)

sleep() solamente simula trabajo. En un programa real, el bucle podría procesar imágenes, leer archivos o enviar solicitudes.

Añadir una descripción

for elemento in tqdm(range(50), desc="Procesando registros"):
    time.sleep(0.04)

Una descripción breve explica qué representa la barra.

Mostrar unidades útiles

archivos = ["a.csv", "b.csv", "c.csv"]

for nombre in tqdm(archivos, desc="Convirtiendo", unit="archivo"):
    time.sleep(0.4)

Para bytes, combina unit="B" con unit_scale=True:

total_bytes = 10_000_000

with tqdm(
    total=total_bytes,
    unit="B",
    unit_scale=True,
    unit_divisor=1024,
    desc="Escribiendo",
) as progreso:
    for tamano in [2_000_000] * 5:
        time.sleep(0.2)
        progreso.update(tamano)

Listas, generadores e iterables

Una lista normalmente proporciona su longitud automáticamente.

nombres = ["Ana", "Luis", "Marta", "Diego"]

for nombre in tqdm(nombres, desc="Saludando"):
    print(nombre)

Un generador puede no informar el total. Pásalo manualmente cuando lo conozcas:

def cuadrados(limite):
    for numero in range(limite):
        yield numero * numero


for valor in tqdm(cuadrados(1000), total=1000, desc="Calculando"):
    pass

Actualizar el progreso manualmente

Cuando el proceso no es un bucle sencillo, crea una barra con total y llama a update().

pasos = ["leer", "validar", "transformar", "guardar"]

with tqdm(total=len(pasos), desc="Proceso", unit="paso") as progreso:
    for paso in pasos:
        time.sleep(0.5)
        progreso.set_postfix(actual=paso)
        progreso.update(1)

Actualiza solamente después de completar el trabajo real correspondiente.

Mostrar métricas cambiantes

errores = 0

with tqdm(range(100), desc="Validando") as progreso:
    for numero in progreso:
        if numero % 17 == 0:
            errores += 1

        progreso.set_postfix(errores=errores)

En bucles extremadamente rápidos, actualizar texto en cada iteración puede ser innecesario.

Escribir mensajes sin romper la barra

from tqdm import tqdm

for numero in tqdm(range(20), desc="Revisando"):
    if numero == 7:
        tqdm.write("Caso especial encontrado en 7")

Para registros permanentes utiliza logging. La barra es una interfaz temporal.

Controlar la frecuencia de actualización

  • mininterval: tiempo mínimo entre actualizaciones.
  • miniters: iteraciones mínimas entre refrescos.
  • disable: desactiva la salida.
  • leave: conserva o elimina la barra completada.
  • dynamic_ncols: adapta el ancho a la terminal.
for elemento in tqdm(
    range(1_000_000),
    mininterval=0.5,
    dynamic_ncols=True,
    leave=False,
):
    resultado = elemento * 2

Desactivar la barra fuera de una terminal

import sys
from tqdm import tqdm

for elemento in tqdm(
    range(100),
    disable=not sys.stderr.isatty(),
):
    pass

Esto evita caracteres de animación en archivos de log o sistemas de integración continua.

Barras anidadas

import time
from tqdm import tqdm

for lote in tqdm(range(3), desc="Lotes", position=0):
    for elemento in tqdm(
        range(20),
        desc=f"Lote {lote + 1}",
        position=1,
        leave=False,
    ):
        time.sleep(0.02)

Evita demasiados niveles porque la terminal puede volverse difícil de leer.

Procesar archivos con pathlib

from pathlib import Path
from tqdm import tqdm

carpeta = Path("documentos")
archivos = list(carpeta.glob("*.txt"))

for ruta in tqdm(archivos, desc="Leyendo", unit="archivo"):
    contenido = ruta.read_text(encoding="utf-8")
    palabras = len(contenido.split())
    print(ruta.name, palabras)

Convertir el resultado a lista permite conocer el total. En directorios enormes, valora si merece la pena cargar todas las rutas.

Usar tqdm con pandas

import pandas as pd
from tqdm.auto import tqdm

tqdm.pandas(desc="Normalizando")

datos = pd.DataFrame({"nombre": ["  Ana ", "LUIS", " marta"]})
datos["limpio"] = datos["nombre"].progress_apply(
    lambda valor: valor.strip().title()
)

print(datos)

Las operaciones vectorizadas de pandas suelen ser más rápidas que apply(). La barra mejora la visibilidad, no el rendimiento.

tqdm.auto en terminal y notebooks

from tqdm.auto import tqdm

for elemento in tqdm(range(100)):
    pass

tqdm.auto selecciona una presentación adecuada en muchos entornos.

Descargar un archivo con progreso

from pathlib import Path
from urllib.request import urlopen
from tqdm import tqdm


def descargar(url, destino, tamano_bloque=64 * 1024):
    destino = Path(destino)

    with urlopen(url, timeout=30) as respuesta:
        total = int(respuesta.headers.get("Content-Length", 0))

        with destino.open("wb") as archivo, tqdm(
            total=total or None,
            unit="B",
            unit_scale=True,
            unit_divisor=1024,
            desc=destino.name,
        ) as progreso:
            while bloque := respuesta.read(tamano_bloque):
                archivo.write(bloque)
                progreso.update(len(bloque))

Si el servidor no envía Content-Length, la barra puede mostrar bytes y velocidad sin porcentaje.

Proyecto: contador de líneas con barra

import argparse
import sys
from pathlib import Path
from tqdm import tqdm


def contar_lineas(ruta):
    with ruta.open("r", encoding="utf-8", errors="replace") as archivo:
        return sum(1 for _ in archivo)


def buscar_txt(carpeta, recursivo=False):
    patron = "**/*.txt" if recursivo else "*.txt"
    return sorted(carpeta.glob(patron))


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("carpeta", type=Path)
    parser.add_argument("--recursivo", action="store_true")
    parser.add_argument("--sin-progreso", action="store_true")
    args = parser.parse_args()

    if not args.carpeta.is_dir():
        raise SystemExit(f"No es una carpeta: {args.carpeta}")

    archivos = buscar_txt(args.carpeta, args.recursivo)
    ocultar = args.sin_progreso or not sys.stderr.isatty()
    total_lineas = 0

    for ruta in tqdm(
        archivos,
        desc="Contando",
        unit="archivo",
        disable=ocultar,
    ):
        total_lineas += contar_lineas(ruta)

    print(f"Archivos: {len(archivos)}")
    print(f"Líneas: {total_lineas}")


if __name__ == "__main__":
    main()

Errores frecuentes

  • No proporcionar total cuando el iterable no expone longitud.
  • Llamar a update() con el total final en vez del incremento.
  • Usar print() repetidamente mientras la barra está activa.
  • Crear una barra nueva en cada iteración.
  • Convertir un generador enorme en lista solamente para calcular su tamaño.
  • Mantener animaciones en logs no interactivos.
  • Creer que tqdm acelera el procesamiento.

Conclusión

tqdm mejora la experiencia de scripts largos sin cambiar su lógica principal. Envuelve iterables conocidos, utiliza actualizaciones manuales para trabajo por bloques, muestra unidades claras y desactiva la animación cuando la salida no sea interactiva.

Una buena barra representa trabajo realmente completado y permanece separada de los registros permanentes de la aplicación.

Lecturas relacionadas

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Uso do módulo random para gerar valores aleatórios em Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    Módulo random de Python: guía completa

    Aprende a usar el módulo random de Python para generar números, elegir elementos, mezclar listas, crear muestras y distinguirlo de

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026