CodeGym /Corsi /Python SELF IT /Introduzione alle Task e al ciclo di eventi

Introduzione alle Task e al ciclo di eventi

Python SELF IT
Livello 25 , Lezione 4
Disponibile

5.1 Event Loop

Ora accenniamo brevemente alla seconda parte dell'asincronicità, che emerge da tutte le parti: Event Loop, Task e Future.

Immagina l'Event Loop come un direttore d'orchestra, Task come i musicisti, e Future come le note che i musicisti devono suonare. Il direttore (Event Loop) coordina il lavoro dei musicisti (Task) che eseguono la musica (operazioni asincrone) leggendo le note (Future).

Il ciclo di eventi (Event Loop) è il fulcro della programmazione asincrona in Python. È responsabile dell'esecuzione delle attività asincrone, della gestione degli eventi e dell'elaborazione dell'I/O. Il ciclo di eventi controlla continuamente la presenza di nuovi eventi o attività e li esegue quando sono pronti.

Funzioni principali

  • run_forever(): Avvia il ciclo di eventi e continua la sua esecuzione fino alla chiamata di stop().
  • run_until_complete(future): Avvia il ciclo di eventi e lo termina dopo il completamento dell'oggetto futuro o della coroutine specificata.
  • stop(): Ferma il ciclo di eventi.
  • create_task(coroutine): Pianifica l'esecuzione della coroutine come attività.

Esempio di utilizzo:


import asyncio

async def hello():
    print("Hello, world!")
    await asyncio.sleep(1)
    print("Hello again!")
            
loop = asyncio.get_event_loop()
loop.run_until_complete(hello())
loop.close()

In questo esempio prima usiamo il metodo get_event_loop() per ottenere l'oggetto corrente EventLoop della libreria asyncio.

Poi aggiungiamo a questo EventLoop la coroutine hello e gli chiediamo di eseguirla usando il metodo run_until_complete().

Nell'ultimo passaggio, chiudiamo il EventLoop con l'aiuto del metodo close().

Quando esegui questo codice vedrai che prima viene stampato "Hello, world!", poi il programma aspetta 1 secondo, e dopo di che viene stampato "Hello again!". Questo dimostra come l'Event Loop gestisce l'esecuzione di una funzione asincrona.

Esamineremo queste azioni in modo più dettagliato nella prossima lezione.

5.2 Tasks

Le Task rappresentano un involucro per le coroutine, permettendo di gestire la loro esecuzione e monitorare il loro stato. Le Task permettono di eseguire le coroutine in parallelo, gestendole attraverso il ciclo di eventi.

Creazione e gestione delle Task

  • asyncio.create_task(coroutine): Crea una Task per l'esecuzione di una coroutine.
  • Task.result(): Restituisce il risultato della Task completata o solleva un'eccezione se la Task è terminata con un errore.
  • Task.cancel(): Annulla l'esecuzione della Task.

Esempio di utilizzo:


import asyncio

async def say_hello():
    await asyncio.sleep(1)
    print("Hello")
            
async def main():
    task = asyncio.create_task(say_hello())
    await task
            
asyncio.run(main())

In questo esempio avvolgiamo la coroutine say_hello() con un oggetto Task. Anch'esso è un oggetto asincrono, quindi per ottenere il suo risultato, dobbiamo applicare al suo interno l'operatore await.

Quando esegui questo codice, il programma aspetta 1 secondo, e poi stampa "Hello". Questo mostra come la Task gestisce l'esecuzione della coroutine e come possiamo attendere il suo completamento usando await.

Più dettagli sulla gestione delle Task Task verranno discussi nella prossima lezione.

5.3 Futures

Gli oggetti Future rappresentano il risultato di un'operazione asincrona, che sarà disponibile in futuro. Consentono di gestire lo stato dell'operazione asincrona impostando il risultato o l'eccezione.

Metodi principali:

  • set_result(result): Imposta il risultato per l'oggetto Future.
  • set_exception(exception): Imposta l'eccezione per l'oggetto Future.
  • result(): Restituisce il risultato dell'oggetto Future o solleva un'eccezione se l'operazione si è conclusa con un errore.
  • exception(): Restituisce l'eccezione se è stata impostata.

Esempio di utilizzo:


import asyncio

async def set_future(fut, value):
    await asyncio.sleep(1)
    fut.set_result(value)
            
async def main():
    loop = asyncio.get_running_loop()
    fut = loop.create_future()
    await set_future(fut, 'Hello, future!')
    print(fut.result())
            
asyncio.run(main())

In questo esempio creiamo un Future, impostiamo il suo valore dopo un secondo, e poi stampiamo il risultato. Vedrai che il programma aspetta un secondo prima di stampare 'Hello, future!'. Questo dimostra come Future rappresenta un risultato che diventerà disponibile in futuro.

A differenza di un oggetto Task, un oggetto Future è legato a un Event Loop specifico, e la funzione asincrona eseguita può scrivere in esso il suo risultato. Anche se di solito funziona un po' diversamente.

Molto spesso, gli oggetti Future vengono utilizzati in combinazione con le Task Task, che forniscono una gestione più sofisticata delle operazioni asincrone.

Ora che ti sei familiarizzato con Event Loop, Task e Future, li esamineremo più da vicino.

Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION