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

    Documento y bandeja de entrada que representan buzones de correo con mailbox en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    mailbox en Python: buzones de correo

    Aprende mailbox en Python para leer, crear y migrar Maildir, mbox y MH con locking, flags, mensajes y manejo seguro

    Ler mais

    Tempo de leitura: 5 minutos
    12/08/2026
    Editor de texto que representa formato con textwrap en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    textwrap en Python: formatea textos

    Aprende textwrap en Python para dividir, rellenar, acortar, indentar y quitar sangrías con control de ancho, espacios y palabras largas.

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Carpeta y lupa que representan filtros de nombres con fnmatch en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    fnmatch en Python: filtra nombres de archivos

    Aprende fnmatch en Python para filtrar nombres de archivos con comodines, controlar mayúsculas, excluir patrones y distinguir glob de regex.

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Monitor con datos binarios que representa arrays numéricos compactos en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    array en Python: números compactos

    Aprende array en Python para almacenar números compactos, usar archivos binarios, byte order, memoryview y buffers seguros.

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Círculo cromático que representa conversiones RGB, HSV y HLS con colorsys en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    colorsys en Python: RGB, HSV y HLS

    Aprende colorsys en Python para convertir colores entre RGB, HSV, HLS y YIQ, crear paletas y evitar errores de escala

    Ler mais

    Tempo de leitura: 5 minutos
    09/08/2026
    Icono de configuración que representa archivos plist con plistlib en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    plistlib: lee y escribe archivos plist

    Aprende plistlib en Python para leer y escribir archivos plist XML y binarios, validar datos y manejar fechas, bytes y

    Ler mais

    Tempo de leitura: 6 minutos
    08/08/2026