Vai al contenuto principale
Pitone intermedio2026-07-29 · 11 min di lettura

Python asincrono/attende spiegato: il tutorial del 2026

Async in Python ha la reputazione di creare confusione. Non deve essere così. Una volta interiorizzata una frase - async consente a UN thread di eseguire più attività legate a I/O interlacciate - tutto il resto segue.

Questo tutorial copre: cosa fanno effettivamente "async def" e "await", quando async vince rispetto a quando è lo strumento sbagliato, i quattro modelli utilizzati da ogni codebase asincrono (sequenziale, raccolta, semaforo, timeout) e i tre modi in cui i principianti ingoiano silenziosamente gli errori.

Il modello mentale di una frase

Async in Python è concorrenza cooperativa in un singolo thread. Quando il codice raggiunge "await", il controllo ritorna al ciclo di eventi, che può eseguire un'altra attività mentre la prima è in attesa di I/O. Una volta completato l'I/O, il ciclo riprende la prima attività da dove era stata sospesa.

Questo è tutto. Nessun thread, nessun processo, nessun parallelismo (nel senso di CPython con GIL). Solo un thread che si destreggia tra molte attività che trascorrono la maggior parte del tempo in attesa su rete/disco/database.

La sincronizzazione è più veloce quando il collo di bottiglia è in attesa, non in elaborazione.

Il programma asincrono minimo vitale di tre righe

▶ PYTHONeditable · runs in your browser
  • async def hello() — dichiara una coroutine. La chiamata a hello() non esegue il codice; crea un oggetto coroutine.
  • await asyncio.sleep(1) — restituisce il controllo al ciclo degli eventi per 1 secondo.
  • asyncio.run(hello()) — crea un ciclo di eventi ed esegue la coroutine fino al completamento.

Regola: `await` solo all'interno di `async def`. Chiamare "await" in una funzione regolare è un "SyntaxError".

Quando l'asincrono vince (e quando no)

L'asincrono vince: lavoro legato all'I/O

Qualsiasi attività che trascorre la maggior parte del suo tempo in ATTESA è un candidato per l'asincrono:

  • Richieste HTTP (API esterne, scraping, webhook)
  • Interrogazioni del database
  • Il file legge/scrive
  • Flussi WebSocket/gRPC
  • Consumatori della coda (Redis, RabbitMQ, Kafka)

Esempio: recupero di 100 URL.

▶ PYTHONeditable · runs in your browser

Accelerazione dell'orologio da parete di 50-100 volte per lavori pesanti di I/O. È qui che l'asincrono guadagna il suo budget di complessità.

Async PERDE: lavoro legato alla CPU

Async non fornisce parallelismo per il calcolo. Poiché è cooperativo a thread singolo, un hot loop della CPU blocca l'intero ciclo di eventi.

▶ PYTHONeditable · runs in your browser

Tutti gli altri task muoiono durante l'esecuzione di pbkdf2. Per il lavoro legato alla CPU, utilizzare "multiprocessing" o "concurrent.futures.ProcessPoolExecutor", non async.

Carico di lavoro misto: run_in_executor

Se UN passaggio è pesante per la CPU e il resto è I/O, esegui il wrap del passaggio della CPU in modo che venga eseguito in un pool di thread senza bloccare il ciclo:

▶ PYTHONeditable · runs in your browser

Il None = pool di thread predefinito. Ottimo per chiamare librerie di sincronizzazione di terze parti che sono lente ma non è possibile riscrivere.

I quattro modelli

1. Sequenziale: un'attività alla volta

▶ PYTHONeditable · runs in your browser

Da utilizzare quando ciascuna richiesta dipende dal risultato di quella precedente.

2. asyncio.gather — attiva tutto in una volta

▶ PYTHONeditable · runs in your browser

Scelta predefinita per attività I/O indipendenti. Ma: se raccogli 10.000 attività su un'API, otterrai descrittori di file con velocità limitata o esaurimento. È qui che entra in gioco lo schema del semaforo.

3. Semaforo: limite alla concorrenza

▶ PYTHONeditable · runs in your browser

"asyncio.Semaphore(N)" consente al massimo N attività di superare "async with sem:" in qualsiasi momento. Le altre attività sono in coda. Utilizzare per qualsiasi API esterna con un limite di velocità o un database con un pool di connessioni.

4. Timeout: abbandona il lavoro lento

▶ PYTHONeditable · runs in your browser

"asyncio.wait_for" annulla l'attività sottostante dopo N secondi. Essenziale per qualsiasi codice asincrono che comunica con una rete: non fare mai un'attesa illimitata.

Le tre trappole per l'inghiottimento degli errori

Trappola 1: asyncio.gather con return_exception=True

▶ PYTHONeditable · runs in your browser

Utile quando vuoi conservare risultati parziali ma LETALE se non controlli tutti i risultati:

▶ PYTHONeditable · runs in your browser

Senza il controllo gli errori svaniscono silenziosamente.

Trappola 2: compiti "spara e dimentica".

▶ PYTHONeditable · runs in your browser

Se si solleva background_work(), Python emette un avviso allo spegnimento e va avanti. Per qualsiasi cosa ti interessi, memorizza l'attività e "aspettala" oppure utilizza "asyncio.TaskGroup" (3.11+) che propaga tutti gli errori.

Trappola 3: sincronizza il codice all'interno di async

▶ PYTHONeditable · runs in your browser

"richieste" è sincrono. Anche all'interno di un async def, requests.get blocca l'intero ciclo finché non arriva la risposta. Utilizza httpx (o aiohttp) per HTTP asincrono.

Regola: non utilizzare mai una libreria I/O sincrona all'interno del codice asincrono. Se la libreria non ha una variante asincrona, racchiuderla in run_in_executor.

asyncio.TaskGroup: il modo del 2026 di distribuirsi a ventaglio

Python 3.11 ha aggiunto TaskGroup, che risolve il problema "fire-and-forget" in modo pulito:

▶ PYTHONeditable · runs in your browser

Concorrenza strutturata: nessun errore perso, nessuna attività orfana. Preferisci questo al semplice create_task nel codice moderno.

Esempio reale: raschiatore a velocità limitata

▶ PYTHONeditable · runs in your browser

Tutti e quattro i modelli in 15 righe: concorrenza limitata (semaforo), timeout (wait_for), rami di errore espliciti (nessuna immissione) e raccolta per fan-out. Copia e incolla questa forma in qualsiasi attività I/O asincrona.


Async in Python ha una vera curva di apprendimento, ma il modello mentale è semplice: un thread, pause cooperative in await, I/O si sovrappone. Padroneggia gather + Semaphore + wait_for + TaskGroup e avrai coperto il 95% del lavoro asincrono che scriverai.

Passaggio successivo: il percorso Python Senior comprende 20 lezioni pratiche su asyncio, TaskGroup, aiohttp/httpx e i modelli di concorrenza di cui sopra, con Python reale in esecuzione nel tuo browser.

Pronto a provarlo?

15 lezioni gratuite previa iscrizione gratuita — nessuna tessera. Prova la piattaforma e poi decidi.

Inizia gratis →

Or unlock every lesson

Pro — $12/mo, unlimited AI, cancel any time. Refund within 14 days worldwide.

See Pro plans →

Get one Python lesson + one career idea every Friday

No spam, no "buy our course now". Three bullets, every Friday. Unsubscribe with one click.