Async e Await in Python
Le parole chiave async
e await
in Python consentono di scrivere codice asincrono in modo più leggibile e gestibile. Questi strumenti permettono di eseguire più attività contemporaneamente senza bloccare il thread principale, migliorando così l’efficienza delle applicazioni che devono gestire operazioni I/O pesanti, come richieste di rete o operazioni su file.
Cos’è il codice asincrono?
Il codice asincrono permette di eseguire operazioni senza attendere che un’attività sia completata prima di passare alla successiva. In Python, il modulo asyncio
introduce il supporto per la programmazione asincrona, e le parole chiave async
e await
sono utilizzate per definire e gestire funzioni asincrone.
Definire una funzione asincrona
Le funzioni asincrone in Python sono definite utilizzando la parola chiave async
. Ecco un esempio di una funzione asincrona che simula una chiamata a un’API esterna:
import asyncio
async def richiesta_api():
print("Inizio richiesta...")
await asyncio.sleep(2) # Simula una richiesta I/O di 2 secondi
print("Risposta ricevuta.")
In questo esempio, asyncio.sleep(2)
rappresenta un’operazione asincrona che attende 2 secondi senza bloccare l’intero programma. La funzione await
sospende l’esecuzione della funzione corrente fino a quando l’operazione asincrona non è completata.
Utilizzare await
per chiamare funzioni asincrone
Per eseguire una funzione asincrona, è necessario usare la parola chiave await
all’interno di un’altra funzione asincrona. Ecco un esempio:
async def main():
print("Avvio del programma...")
await richiesta_api()
print("Fine del programma.")
asyncio.run(main())
In questo esempio, la funzione await
permette di eseguire richiesta_api()
senza bloccare l’esecuzione del codice che segue, come “Fine del programma.”.
Lavorare con più operazioni asincrone
Uno dei principali vantaggi della programmazione asincrona è la capacità di gestire più operazioni contemporaneamente. Con l’uso di asyncio.gather()
, possiamo eseguire più funzioni asincrone in parallelo:
async def main():
task1 = richiesta_api()
task2 = richiesta_api()
await asyncio.gather(task1, task2)
asyncio.run(main())
In questo esempio, due funzioni richiesta_api()
vengono eseguite contemporaneamente, risparmiando tempo ed evitando che una operazione blocchi l’altra.
Quando utilizzare async
e await
- I/O intensivo: Le parole chiave
async
eawait
sono particolarmente utili per le operazioni che coinvolgono I/O, come il download di dati da una API, la lettura/scrittura di file, o le operazioni su database remoti. - Event loop: Python utilizza un event loop per gestire le operazioni asincrone. È importante non bloccare l’event loop con operazioni sincrone che richiedono molto tempo, come calcoli intensivi o operazioni bloccanti.
Vantaggi e Limitazioni
Vantaggi
- Efficienza: Permette al programma di continuare a funzionare mentre attende operazioni lunghe come richieste di rete o accessi a database.
- Migliore gestione delle risorse: Riduce il consumo di risorse, specialmente in applicazioni che devono gestire molte connessioni contemporaneamente.
Limitazioni
- Calcoli CPU intensivi: Le operazioni CPU-bound non traggono vantaggio dall’asincronismo, poiché non implicano attese I/O. In questi casi, la multithreading o multiprocessing potrebbe essere più efficace.
- Sintassi non sempre intuitiva: L’introduzione di parole chiave
async
eawait
potrebbe aumentare la complessità del codice, rendendo più difficile la comprensione.
Conclusione
Le parole chiave async
e await
sono strumenti potenti per la gestione di operazioni asincrone in Python. Grazie a questi strumenti, è possibile migliorare l’efficienza delle applicazioni, soprattutto in contesti I/O intensivi. Con una corretta implementazione, è possibile evitare blocchi nel thread principale e rendere il codice più reattivo e scalabile.