9.1 Gestori di contesto
Ti ricordi come abbiamo usato l'operatore with
per
controllare l'accesso a una risorsa? Con esso potevamo monitorare esattamente,
quando la risorsa iniziava ad essere utilizzata e quando questo processo finiva. La stessa cosa
possiamo farla anche per le "risorse asincrone".
I gestori di contesto asincroni (AsyncContextManager)
vengono utilizzati per
gestire le risorse nella programmazione asincrona, garantendo la corretta apertura
e chiusura delle risorse nelle funzioni asincrone. Funzionano in modo simile ai
gestori di contesto normali, ma sono progettati per l'uso nelle
funzioni asincrone con le parole chiave
async with
.
Non voglio andare troppo nei dettagli, dato che probabilmente non creerai i tuoi gestori di contesto asincroni nel prossimo futuro, e quando deciderai di farlo, te ne sarai comunque dimenticato. Ma voglio presentarti il concetto di base.
Creazione di un gestore di contesto asincrono
I gestori di contesto asincroni vengono definiti utilizzando i metodi
__aenter__
e __aexit__
. Questi metodi sono analoghi ai metodi __enter__
e
__exit__
nei gestori di contesto normali, ma sono asincroni.
-
__aenter__()
: Metodo asincrono chiamato all'ingresso nel contesto. -
__aexit__(exc_type, exc, tb)
: Metodo asincrono chiamato all'uscita dal contesto. Accetta tre argomenti: tipo di eccezione, eccezione stessa etraceback
.
Esempio di creazione di un gestore di contesto asincrono
import asyncio
class AsyncContextManager:
async def __aenter__(self):
print("Enter context")
return self
async def __aexit__(self, exc_type, exc, tb):
print("Exit context")
async def main():
async with AsyncContextManager():
print("Inside context")
asyncio.run(main())
Ecco come verrà eseguito questo codice:
- La funzione
main()
verrà avviata in modo asincrono - La funzione
main()
inizierà ad essere eseguita - Verrà creato un oggetto di tipo
AsyncContextManager
- Verrà chiamato il metodo
__aenter__()
dell'oggettoAsyncContextManager
- Verrà stampato
print("Enter context")
- Verrà eseguito il codice
print("Inside context")
- Verrà chiamato il metodo
__aexit__()
dell'oggettoAsyncContextManager
- La funzione
main()
terminerà
9.2 Esempi di utilizzo
Nell'esempio precedente non è necessario utilizzare la versione asincrona del gestore di contesto – il codice funzionerà anche se lo rendi sincrono.
Ma il gestore asincrono è necessario se dentro il blocco
with
viene chiamata una funzione asincrona oppure
viene utilizzato l'operatore
await
.
Gestore di contesto asincrono per lavorare con i file
In questo esempio viene utilizzata la libreria aiofiles
per la lettura e
scrittura dei file in modo asincrono. Il gestore di contesto asincrono aiofiles.open
consente
di aprire e chiudere i file in modo sicuro in un contesto asincrono.
import aiofiles
import asyncio
async def main():
async with aiofiles.open('example.txt', mode='w') as file:
await file.write('Hello, world!')
asyncio.run(main())
Gestore di contesto asincrono per operazioni di rete
In questo esempio viene utilizzata la libreria aiohttp
per eseguire
richieste HTTP asincrone. I gestori di contesto asincroni ClientSession
e session.get
garantiscono la corretta gestione delle connessioni.
import aiohttp
import asyncio
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def main():
html = await fetch('https://example.com')
print(html)
asyncio.run(main())
I gestori di contesto asincroni assicurano la gestione automatica delle risorse, come file, connessioni di rete e altre risorse che devono essere aperte e chiuse.
I metodi __aenter__
e __aexit__
consentono di eseguire operazioni asincrone all'ingresso
e all'uscita dal contesto, garantendo l'esecuzione parallela delle attività.
L'uso dei gestori di contesto asincroni aiuta a evitare perdite di
risorse e garantisce che tutte le risorse vengano rilasciate correttamente.
GO TO FULL VERSION