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