Corso
Ti è mai capitato di chiederti se stesse succedendo qualcosa dietro lo schermo mentre un lungo script Python continuava a girare?
L’incertezza sull’avanzamento potrebbe portarti a interrompere un’esecuzione quasi completata o ad aspettare all’infinito uno script che in realtà si è già bloccato.
La libreria tqdm per Python risolve questo problema fornendo indicatori di avanzamento per i tuoi script.

Cos’è tqdm?
Tqdm è una libreria Python che fornisce barre di avanzamento veloci ed estensibili per loop e iterabili. È un modo semplice per tenere traccia dell’avanzamento di attività che richiedono tempo.
Il nome della libreria significa "progresso" in arabo (taqadum, تقدّم) ed è anche un’abbreviazione di "ti voglio troppo bene" in spagnolo (te quiero demasiado).
Tdqm tiene traccia dell’avanzamento e aggiorna la barra contando le iterazioni, calcolando il tempo trascorso e quello rimanente e visualizzando il progresso complessivo nel riempimento della barra.
Usa algoritmi intelligenti per stimare il tempo rimanente e salta aggiornamenti superflui per ridurre l’overhead. Usare tqdm offre diversi vantaggi, tra cui:
- Feedback visivo: Le barre di avanzamento permettono di vedere quanta parte di un’attività è completa e di stimare quanto potrebbe richiedere la parte restante.
- Funziona ovunque: La libreria
tqdmfunziona su qualsiasi piattaforma (Linux, Windows, Mac, FreeBSD, NetBSD, SunOS), in qualsiasi console o in una GUI. - Integrazione semplice:
Tqdmsi integra senza problemi con i notebook Jupyter, librerie comuni come Pandas e costrutti Python comuni come i loop. - Personalizzazione: Offre diverse opzioni per adattare aspetto e comportamento delle barre di avanzamento, che vedremo più avanti.
- Prestazioni: mentre pacchetti simili come ProgressBar hanno un overhead di 800ns/iterazione, l’overhead di tdqm di 60ns/iterazione è molto più veloce.
Come installare Tqdm
Come per la maggior parte delle librerie Python, il modo più semplice per installare tqdm è usare il gestore pacchetti pip.
pip install tqdm
Tqdm: esempio semplice
Per creare una barra di avanzamento, avvolgiamo il nostro iterabile con la funzione tqdm() (che importiamo dal modulo tqdm). Vediamo un esempio semplice. La funzione time.sleep(0.01) funge da segnaposto per il codice da eseguire a ogni iterazione.
from tqdm import tqdm
for i in tqdm(range(1000)):
time.sleep(0.01)
# …

Come scorciatoia per tdqm(range(n)) puoi anche usare trange(n). Il seguente codice restituirà esattamente lo stesso output del precedente:
from tqdm import tqdm
for i in trange(1000):
time.sleep(0.01)
# …
Entrambi gli esempi restituiranno una barra di avanzamento come quella sopra.
Osserva più da vicino la barra per capire quali informazioni fornisce. Vediamo nel dettaglio cosa mostra tqdm:
- Indicatori di avanzamento:
- Percentuale di iterazioni
- Riempimento della barra
- Frazione del totale delle iterazioni
- Metriche:
- Tempo trascorso
- Tempo stimato rimanente
- Prestazioni (iterazioni al secondo)
Personalizzare Tqdm: rendi tue le barre di avanzamento
Tqdm offre varie opzioni di personalizzazione per adattare aspetto e comportamento delle barre di avanzamento. Vedremo i parametri più importanti prima di passare a casi d’uso più avanzati di tqdm.
Aggiungere una descrizione alla barra di avanzamento
Una personalizzazione comune è aggiungere un’etichetta descrittiva usando il parametro desc, rendendo la barra più informativa e aiutando a tenere una panoramica dei diversi iterabili.
Per esempio, aggiungendo il parametro desc=”Processing large range” verrà mostrato il titolo “Processing large range” a sinistra della barra.
for _ in tqdm(range(20000000), desc="Processing large range"):
continue
Ti invito a eseguire il codice sopra nel tuo ambiente con e senza il parametro desc e notare le differenze.
Specificare il numero totale di iterazioni
Il parametro total specifica il numero totale di iterazioni nel loop, consentendo a tqdm di fornire stime più accurate del tempo rimanente e della percentuale di completamento.
In un esempio base che usa tqdm(range()) o trange() non è necessario, poiché il numero di iterazioni è già indicato tra parentesi. Tuttavia, ci sono due scenari principali in cui aggiungere il parametro total=n (con n come numero totale) può essere utile:
1. Iterabili senza metodo len(): per iterabili senza metodo len(), come i generatori con numero di elementi sconosciuto, devi fornire manualmente il valore total. Senza questo parametro, tqdm() mostrerà solo il conteggio delle iterazioni completate. Nota che la barra ricomincia se il numero effettivo di elementi supera il total specificato.
from tqdm import tqdm
import time
import random
# Function generating random number between 1 and 100
def generate_random_numbers():
while True:
yield random.randint(1, 100)
# Without total: tqdm() only shows number of iterations, does not know total
for num in tqdm(generate_random_numbers(), desc=’Random Iteration’):
time.sleep(0.01)
# …

Ecco come appare se il numero di elementi è sconosciuto e non specifichiamo il totale.
# With total (assuming you know the desired number of iterations): tqdm() shows progress
num_iterations = 1000
for num in tqdm(generate_random_numbers(), total=num_iterations, desc="Random Iteration"):
time.sleep(0.01)
# …

Molto meglio, ora la barra di avanzamento si vede!
2. Aggiornamenti manuali: se aggiorniamo manualmente la barra all’interno di una funzione usando il metodo update(), è necessario specificare il valore total per garantire un tracciamento corretto. Il metodo update() permette, ad esempio, di rispondere a processi che cambiano dinamicamente o di implementare un tracciamento personalizzato. Ne parleremo tra poco.
Ritoccare l’aspetto visivo
Se vogliamo modificare l’ordine di posizionamento degli elementi della barra, possiamo impostare il parametro bar_format con la stringa di formato preferita. In questo modo controlliamo la posizione di vari elementi come percentuale, tempo trascorso e carattere di riempimento. Per maggiori dettagli, consulta la documentazione.
Un’altra regolazione dell’aspetto visivo si ottiene con il parametro colour. È possibile usare sia nomi come ‘green’ sia stringhe in esadecimale come ‘#00ff00’.
Il parametro leave riguarda più la scomparsa che l’aspetto: determina se la barra rimane visibile dopo il completamento. Se impostato su True, la barra rimane dopo la fine del loop; se impostato su False, scompare.
Vediamo le differenze visive in un altro esempio. Il codice seguente crea tre barre: una con impostazioni predefinite, una in cui cambiano ordine degli elementi e colore, e una che è impostata per scomparire al termine. Gli output sono visibili nella GIF qui sotto.
from tqdm import tqdm
import time
# Progress bar 1: Default settings
for i in tqdm(range(300)):
time.sleep(0.01)
# Progress bar 2: Customized bar format and color
for i in tqdm(range(300), bar_format='[{elapsed}<{remaining}] {n_fmt}/{total_fmt} | {l_bar}{bar} {rate_fmt}{postfix}', colour='yellow'):
time.sleep(0.01)
# Progress bar 3: Customized bar format and color, leave=False
for i in tqdm(range(300), bar_format='[{elapsed}<{remaining}] {n_fmt}/{total_fmt} | {l_bar}{bar} {rate_fmt}{postfix}', colour='red', leave=False):
time.sleep(0.01)

Uso avanzato: gestire scenari più complessi
Ora che sappiamo creare una barra semplice e personalizzarla, possiamo passare ad alcuni casi più avanzati.
Barre di avanzamento annidate
I loop annidati sono loop contenuti all’interno di altri loop. Di conseguenza, le barre annidate sono una serie di barre per ogni iterazione dei loop contenuti in altri loop. Per crearle, avvolgi ciascun loop con una funzione tqdm() e aggiungi etichette descrittive per ogni iterabile.
Il codice seguente ha tre loop annidati e mostra come appaiono le barre annidate:
from tqdm import trange
import time
for i in trange(3, desc='outer loop'):
for j in trange(2, desc='middle loop'):
for k in trange(6, desc='inner loop'):
time.sleep(0.01)

Nel risultato finale sopra, possiamo riconoscere uno schema nell’aggiornamento delle diverse barre. Tqdm partirà sempre dal loop più esterno fino a raggiungere quello più interno, le cui iterazioni verranno elaborate aggiornando la barra corrispondente.
Supponiamo di avere tre loop annidati, come nell’esempio. Dopo la prima iterazione interna, si passa al loop intermedio, lo si aggiorna segnando un’iterazione completata, per poi tornare all’iterabile interno. Questo processo si ripete finché il loop intermedio non è completato, il che fa apparire la barra esterna con un’iterazione completa.
Lo stesso accade tra loop esterno e intermedio. Alla fine, l’ultima esecuzione interna completa l’iterabile intermedio, che a sua volta completa l’ultima iterazione esterna.
Aggiornamenti manuali
Aggiornare manualmente le barre con tqdm può essere utile in vari scenari:
- Iterabili di lunghezza sconosciuta: quando lavoriamo con iterabili senza lunghezza definita (ad esempio generatori, stream di rete), possiamo aggiornare manualmente la barra in base alla quantità di dati elaborati o al numero di operazioni completate.
- Processi che cambiano dinamicamente: se il numero di iterazioni o il tempo per iterazione può cambiare durante l’esecuzione, gli aggiornamenti manuali permettono di adeguare la barra di conseguenza.
- Tracciamento personalizzato: per un controllo più granulare, possiamo aggiornarla manualmente in base a criteri o eventi specifici. Ad esempio, potremmo voler aggiornare la barra al completamento di determinate milestone o del progresso di singoli task all’interno di un processo più grande.
- Integrazione con sistemi esterni: se integriamo
tqdmcon sistemi o librerie esterne che non forniscono un modo naturale per tracciare l’avanzamento, gli aggiornamenti manuali possono sincronizzare la barra con il processo esterno.
Per aggiornare manualmente una barra tqdm, è importante specificare il parametro total come stima del numero massimo previsto di iterazioni. Poi, man mano che il codice elabora ogni nuovo elemento, la barra va aggiornata usando il metodo update(). Il valore di aggiornamento dovrebbe rappresentare il numero di iterazioni elaborate dall’ultimo aggiornamento.
Poniamo di aspettarci che il nostro iterabile contenga fino a 750 elementi. In questo esempio, la lunghezza effettiva è un numero casuale tra 100 e 1000, a noi sconosciuto. Inizializziamo progress_bar, impostando estimated_total a 750. Poi iteriamo sui dati, aggiornando la barra dopo ogni elemento elaborato.
from tqdm import tqdm
def process_data(data):
time.sleep(0.01) # simulate processing data
processed_data = data
return processed_data
# Generate an iterable with random length between 100 and 1,000
random_length = random.randint(100, 1000)
data_list = [i for i in range(random_length)]
# Define estimated maximum number of iterations
estimated_total = 750
# Define the progress bar using the estimated_total
progress_bar = tqdm(total=estimated_total)
# Iterating through data list of unknown length
for data in data_list:
processed_data = process_data(data)
progress_bar.update(1)

Abbiamo sottostimato la lunghezza dell’iterabile, quindi l’output continua a contare dopo aver raggiunto il 100%.
Multiprocessing
Multiprocessing e threading sono tecniche per eseguire task in parallelo, migliorando prestazioni e reattività. In questi scenari può essere difficile tracciare l’avanzamento dei singoli task o quello complessivo dell’esecuzione parallela. Tqdm è uno strumento prezioso per fornire feedback visivo e monitorare l’avanzamento di queste operazioni concorrenti.
Il modulo tqdm.contrib.concurrent fornisce funzioni specializzate per creare barre in contesti di multiprocessing o threading. Queste funzioni gestiscono sincronizzazione e comunicazione tra processo principale e processi o thread worker, assicurando aggiornamenti corretti. Sono progettate per funzionare senza problemi con l’API concurrent.futures, usando ProcessPoolExecutor() o ThreadPoolExecutor().
Ecco un esempio con il modulo tqdm.contrib.concurrent.futures:
import concurrent.futures
from tqdm.contrib.concurrent import process_map
def process_data(data):
for i in tqdm(range(100), desc=f"Processing {data['name']}"):
# Process data
time.sleep(0.01)
if __name__ == '__main__':
with concurrent.futures.ProcessPoolExecutor() as executor:
results = process_map(process_data, [
{'name': 'dataset1'},
{'name': 'dataset2'},
# …
])
In questo esempio, la funzione process_data() include una barra tqdm per tracciarne l’avanzamento. process_data() verrà eseguita in parallelo per ciascun elemento nella lista. Questo significa che verranno mostrate più barre contemporaneamente, ognuna per un processo separato. Il parametro desc è impostato per creare dinamicamente una descrizione basata sul nome del dataset corrispondente, aiutandoci a distinguere le diverse barre.
Integrazione con pandas
Il modulo tqdm.pandas offre un modo comodo per aggiungere barre alle operazioni pandas. È particolarmente utile per operazioni che richiedono tempo su grandi DataFrame, poiché fornisce feedback visivo sull’avanzamento. Possiamo applicare il decorator tqdm.pandas() a qualsiasi funzione pandas che operi su righe o colonne.
Per iniziare, definiamo un DataFrame casuale con 100.000 righe e richiamiamo il decorator tqdm.pandas(). Se vogliamo personalizzare la barra, questo è il momento giusto, dato che le funzioni progress_apply() e progress_map() non accettano i parametri di tqdm(). Qui vogliamo dare un nome alle barre seguenti, quindi specifichiamo anche il parametro desc.
import pandas as pd
import numpy as np
from tqdm import tqdm
df = pd.DataFrame(np.random.randint(0, 10, (100000, 6)))
tqdm.pandas(desc='DataFrame Operation')
Ora possiamo applicare funzioni a righe, colonne o all’intero DataFrame. Invece di usare una delle funzioni apply() o map(), richiama progress_apply() o progress_map() e verrà mostrata la barra. Ricorda che apply() e progress_apply() si possono applicare a DataFrame, righe o colonne, mentre map() e progress_map() si possono applicare solo a Series o colonne. Per esempio:
# Halving each value in the DataFrame using progress_apply()
Result_apply = df.progress_apply(lambda x: x / 2)
# Doubling each element of the first column using progress_map()
result_map = df[0].progress_map(lambda x: x * 2)
Tqdm: problemi comuni e soluzioni
Vediamo alcuni problemi ed errori comuni con Tqdm e come risolverli.
La barra non si aggiorna
Uno dei problemi più comuni usando tqdm è una barra che non si aggiorna. Spesso dipende dal buffering, in particolare in ambienti come Jupyter Notebook. Quando l’output è bufferizzato, la barra potrebbe non essere mostrata o aggiornata subito, dando l’impressione di un processo bloccato.
Usare il modulo tqdm.notebook può risolvere i problemi di buffering e garantire aggiornamenti corretti in Jupyter. Questo modulo fornisce una barra basata su GUI pensata per tali ambienti.
Inoltre, offre comode indicazioni cromatiche (blu: normale, verde: completata, rosso: errore/interruzione).
Se interrompiamo il codice dell’esempio con barre annidate, appare così:

Barre annidate in Python con tqdm.notebook, che illustrano lo schema di colori per barre completate e interrotte.
Un altro modo efficace per risolvere barre che non si aggiornano è svuotare esplicitamente lo stream di output. Quando i dati vengono scritti sullo standard output (ad esempio con print()), in genere sono bufferizzati prima di essere inviati al dispositivo di output. Svuotare lo stream forza l’interprete Python a inviare subito i dati bufferizzati, assicurando che vengano mostrati senza ritardi.
Per svuotare l’output, usa il metodo flush() dello stream standard. Per un output più reattivo, valuta di svuotare più spesso, magari ogni poche iterazioni o dopo un certo tempo. Tieni presente il compromesso: svuotare frequentemente introduce overhead. Ecco un esempio di come incorporarlo in un semplice processo tqdm:
import sys
import time
from tqdm import tqdm
for i in tqdm(range(100)):
time.sleep(0.1)
sys.stdout.flush() # Flush the output stream after each iteration
Problemi di compatibilità
Sebbene tqdm sia generalmente compatibile con la maggior parte degli ambienti e librerie Python, possono verificarsi problemi di compatibilità o comportamenti inattesi. Alcuni scenari comuni da considerare:
- Stream di output personalizzati: quando si usano stream personalizzati o si reindirizza l’output su file,
tqdmpotrebbe non funzionare come previsto. Dobbiamo assicurarci che lo stream supporti le operazioni necessarie per mostrare la barra. - Librerie di terze parti: in alcuni casi,
tqdmpuò interagire in modo inatteso con librerie di terze parti, soprattutto quelle che gestiscono esse stesse l’output o il tracciamento dell’avanzamento. Possiamo provare a disabilitare o modificare le relative funzionalità per vedere se il problema si risolve. - Compatibilità di versione: è sempre buona pratica usare versioni compatibili di
tqdme delle altre librerie. Controlla la documentazione per eventuali problemi noti con specifiche versioni di Python o altre dipendenze.
Quando incontriamo problemi di compatibilità, possiamo valutare questi workaround:
- Downgrade o upgrade: proviamo una versione diversa di
tqdm. - Modificare il codice: se necessario, apportiamo aggiustamenti per aggirare conflitti di compatibilità.
- Chiedere aiuto alla community: se nulla funziona, possiamo chiedere supporto alla community di
tqdmo nei forum online per assistenza e possibili soluzioni.
Tenendo a mente questi potenziali problemi di compatibilità e le relative soluzioni, possiamo diagnosticare e risolvere efficacemente gli inconvenienti incontrati usando tqdm nei nostri progetti Python.
Conclusione
In conclusione, Tqdm è una libreria Python che ci fornisce barre di avanzamento e altre statistiche utili, rendendo più semplice monitorare e gestire l’esecuzione del codice.
Che tu stia iterando su grandi dataset, addestrando modelli di machine learning o eseguendo qualsiasi altra operazione che richiede tempo, tqdm offre un modo semplice ma potente per tenere traccia dell’avanzamento e restare informato sullo stato del tuo codice.
Per approfondire, dai un’occhiata agli altri tutorial Python di DataCamp, alla documentazione di Tqdm o al suo codice sorgente e Readme su GitHub.
FAQ
Come creo una semplice barra di avanzamento con tqdm?
Installa e importa la libreria tqdm, poi avvolgi il tuo iterabile con la funzione tqdm().
Posso usare tqdm con i DataFrame di pandas o altre librerie?
Sì, puoi usare tqdm con i DataFrame di pandas e altre librerie. Il modulo tqdm.pandas fornisce funzioni specifiche per integrare tqdm con pandas.
Posso personalizzare l’aspetto della barra di avanzamento di Tqdm?
Sì, puoi personalizzare formato della barra, colore, numero totale di iterazioni e altro tramite i parametri di Tqdm.
La barra di avanzamento di Tqdm non si aggiorna correttamente, cosa posso fare?
Controlla problemi di buffering, specialmente in Jupyter Notebook. Prova tqdm.notebook o svuota esplicitamente l’output. Assicurati anche di usare correttamente il parametro total.
Tom è un data scientist e formatore tecnico. Scrive e gestisce i tutorial e i post del blog di DataCamp su data science. In precedenza, Tom ha lavorato nella data science presso Deutsche Telekom.


