8.13. Controllo del loop#

La maggior parte degli script asyncio non tocca mai direttamente l’event loop – asyncio.run() è sufficiente. Questa pagina copre l’interfaccia Loop per i casi in cui non lo è: l’installazione di un gestore di eccezioni, l’esecuzione del loop con un ciclo di vita diverso da run, o il mantenimento dell’oggetto loop per scopi di strumentazione.

8.13.1. Ottenere il loop#

  • asyncio.get_event_loop() – restituisce l’oggetto Loop. Può essere chiamato in sicurezza da dentro o fuori una coroutine.

  • asyncio.new_event_loop() – su MicroPython, reimposta lo stato del loop esistente invece di crearne uno nuovo. Vale la pena ripetere la nota: c’è esattamente un event loop per programma.

Non esiste alcuna API per eseguire il loop diversa dai metodi di Loop e da asyncio.run().

8.13.2. Eseguire il loop direttamente#

asyncio.run() è il punto di ingresso giusto per quasi ogni applicazione. Esistono due metodi di Loop per i casi in cui non lo è.

  • run_until_complete() – dato un oggetto awaitable, esegue il loop finché quell’awaitable non termina, quindi restituisce il suo risultato. Equivalente a una singola chiamata a asyncio.run(), ma senza lo smantellamento del loop.

  • run_forever() – esegue il loop finché stop() non viene chiamato dall’interno di un task. Nessun awaitable di primo livello; ci si aspetta che l’appluicazione pianifichi tutto ciò che le serve tramite asyncio.create_task() prima di chiamare run_forever.

I metodi associati sono stop() (richiede l’arresto del loop dopo il termine del task corrente) e close() (libera le risorse del loop).

8.13.3. Creazione di task lato loop#

  • create_task() – stessa operazione di asyncio.create_task(). La funzione libera esiste perché il codice applicativo non abbia bisogno di un riferimento al loop nel caso comune; il metodo esiste per la strumentazione che ne possiede già uno.

8.13.4. Gestori di eccezioni#

Il loop chiama un gestore quando un task solleva un’eccezione che nulla nella catena di chiamate delle coroutine ha catturato – un caso tipico è un task creato dall’applicazione con asyncio.create_task() e mai atteso. Il gestore predefinito stampa un traceback attraverso sys.stderr; la pagina sulle eccezioni ha mostrato come sostituirlo con qualcosa di personalizzato.

  • set_exception_handler() – installa un gestore personalizzato. Il gestore è un callable handler(loop, context) dove context è un dizionario che contiene almeno 'message' e di solito 'exception' e 'future'.

  • get_exception_handler() – restituisce il gestore attualmente installato, oppure None se è in uso quello predefinito.

  • default_exception_handler() – il gestore integrato. Utile all’interno di un gestore personalizzato che vuole eseguire anche il comportamento predefinito (registrare su flash e stampare un traceback, per esempio).

  • call_exception_handler() – esegue il gestore attualmente installato con un dizionario di contesto costruito a mano. Usato per lo più dal loop stesso; un’applicazione ne ha raramente bisogno.