A volte, durante l’esecuzione di un programma, è necessario fare una pausa: attendere il caricamento dei dati, dare tempo all’utente di inserire un input o ridurre il carico sul sistema. Uno dei modi più semplici per farlo in Python è usare la funzione time.sleep(), che sospende l’esecuzione del programma per un intervallo di tempo specificato.
In questo articolo analizzeremo come funziona time.sleep() in Python, le sue caratteristiche e alternative, gli errori più comuni e quando è opportuno utilizzarla nei programmi multithread e asincroni, oppure sostituirla con asyncio.sleep() o altri meccanismi di attesa.
La funzione sleep() è stata introdotta nella libreria standard di Python per semplificare la creazione di pause nel codice. Fa parte del modulo time e si richiama come time.sleep(), permettendo di sospendere temporaneamente l’esecuzione del programma per un certo numero di secondi.
In pratica, sleep() è utile nei test, per inserire ritardi tra richieste API o intervalli tra messaggi. Tuttavia, non deve essere confusa con strumenti di sincronizzazione dei thread o con operazioni che richiedono precisione temporale elevata — per queste ultime esistono soluzioni più adatte.
La funzione time.sleep() mette in pausa il thread corrente per il numero di secondi specificato. In un programma multithread, gli altri thread continuano a funzionare, mentre quello in cui è stata chiamata la funzione rimane “bloccato” per la durata dell’intervallo.
È importante notare che time.sleep() blocca l’esecuzione del codice in quel punto, ritardando tutte le operazioni successive. Ignorare questo comportamento può portare a riduzioni di prestazioni o addirittura al congelamento dell’interfaccia utente in applicazioni desktop.
time.sleep() viene utilizzata soprattutto in fase di test o debug, quando è necessario introdurre un breve ritardo — ad esempio per verificare una risposta API o attendere un server. Si usa anche per eseguire script passo dopo passo, dando all’utente il tempo di leggere le informazioni o inserire dati.
Nelle dimostrazioni e nei tutorial, time.sleep() serve a simulare processi più lunghi, e quando si lavora con servizi esterni, evita sanzioni o blocchi dovuti a richieste troppo frequenti. Tuttavia, non è l’unico modo per rallentare l’esecuzione del codice — vediamo alcune alternative.
Usare time.sleep() in Python è molto semplice, anche per i principianti. Tuttavia, è utile conoscerne i dettagli, poiché possono influire sulle prestazioni o sul comportamento del programma.
Per usare la funzione, importa prima il modulo time:
import time
time.sleep(5)
In questo esempio, il programma “dorme” per 5 secondi. Il parametro passato può essere un numero intero o decimale, permettendo di specificare anche frazioni di secondo.
Sintassi:
time.sleep(seconds)
La funzione non restituisce alcun valore. Sospende semplicemente il thread corrente per la durata indicata.
Ecco un piccolo script che stampa messaggi con un intervallo di 2 secondi:
import time
print("First message")
time.sleep(2)
print("Second message")
time.sleep(2)
print("Third message")
Durante l’esecuzione, l’utente vedrà una pausa di 2 secondi tra ogni messaggio. Questo è esattamente come funziona il ritardo con time.sleep(2).
La funzione accetta un solo parametro, ma può essere un intero o un float. Questo la rende flessibile per diverse situazioni.
Nella maggior parte dei casi si passa un numero intero:
time.sleep(10)
Lo script si ferma per 10 secondi, utile per pause lunghe o per limitare la frequenza delle richieste.
A volte serve una pausa brevissima. Puoi passare un numero con la virgola:
time.sleep(0.5)
Questo crea una pausa di mezzo secondo. Tieni presente che, a causa delle limitazioni del sistema operativo e del timer interno di Python, il ritardo effettivo può essere leggermente più lungo. Per sistemi real-time o ad alta precisione, è meglio usare timer dedicati.
Anche se time.sleep() è la soluzione più comune e semplice, esistono alternative più efficaci in determinati contesti, soprattutto quando si gestiscono eventi esterni o più thread.
Il modo più semplice per fermare un programma è con input(). Questa funzione sospende l’esecuzione finché l’utente non preme Invio o inserisce del testo.
print("Press Enter to continue...")
input()
print("Resuming program execution")
Tecnicamente non è una pausa temporizzata, ma un’attesa di input. Può essere utile durante la debug o negli script interattivi.
Nei programmi multithread, puoi utilizzare un oggetto di sincronizzazione come threading.Event(), che blocca un thread finché non riceve un segnale.
import threading
event = threading.Event()
def worker():
print("Starting work in thread")
event.wait()
print("Event received, resuming work")
thread = threading.Thread(target=worker)
thread.start()
import time
time.sleep(3)
event.set()
In questo caso, il thread rimane bloccato fino alla chiamata di event.set(). È un approccio più flessibile perché permette di “risvegliare” il thread in qualsiasi momento.
In programmazione asincrona (modulo asyncio), si utilizza asyncio.sleep(). A differenza di time.sleep(), non blocca l’intero thread, ma solo la coroutine corrente, consentendo al ciclo di eventi di continuare a eseguire altre attività.
import asyncio
async def main():
print("Start async work")
await asyncio.sleep(2)
print("2 seconds passed, resuming")
asyncio.run(main())
È particolarmente utile quando più funzioni asincrone devono eseguire in parallelo. Se usi time.sleep() in questo contesto, bloccheresti l’intero event loop.
Sebbene time.sleep() sia semplice, un uso improprio può provocare blocchi indesiderati o rallentamenti. È fondamentale capire come influenza il flusso del programma.
time.sleep() blocca il thread in cui è chiamata. Se viene utilizzata nel thread principale di un’applicazione GUI (come Tkinter o PyQt), l’interfaccia può congelarsi.
💡 Suggerimento:
Usa time.sleep() solo in thread secondari, oppure sostituiscila con asyncio.sleep() per evitare blocchi. Nelle applicazioni grafiche è meglio usare timer come QTimer o after().
In un programma multithread, time.sleep() può essere chiamata separatamente in ogni thread, ma non rilascia automaticamente il Global Interpreter Lock (GIL). La possibilità per altri thread di continuare dipende dal sistema operativo.
Nel codice asincrono, non usare time.sleep() all’interno di un ciclo di eventi (asyncio.run()), poiché lo bloccherebbe completamente. Usa invece asyncio.sleep(), che restituisce il controllo al pianificatore, permettendo l’esecuzione di altre coroutine.
Supponiamo di scrivere uno script che interroga un’API esterna, ma le sue regole impongono un minimo di 30 secondi tra ogni richiesta.
Soluzione con time.sleep():
import time
def poll_api():
print("Making API request...")
def main():
while True:
poll_api()
time.sleep(30)
if __name__ == "__main__":
main()
Dopo ogni richiesta, lo script si ferma per 30 secondi, rispettando i limiti.
Alternativa asincrona:
import asyncio
async def poll_api():
print("Making API request...")
async def main():
while True:
await poll_api()
await asyncio.sleep(30)
if __name__ == "__main__":
asyncio.run(main())
Questa versione non blocca l’intero programma: altre attività possono eseguire in parallelo nello stesso ambiente asincrono. È una soluzione più efficiente e scalabile.
Gestire pause e ritardi è un aspetto importante nello sviluppo in Python.
time.sleep() è lo strumento più immediato, ma la scelta tra time.sleep(), asyncio.sleep() o altri metodi dipende dall’architettura del progetto.
Usa time.sleep() per pause brevi nei test, tra richieste o in dimostrazioni.
Evita di bloccare il thread principale nelle applicazioni GUI.
Nel codice asincrono, sostituiscila con asyncio.sleep().
Nei programmi multithread, ricorda che solo il thread corrente si ferma.