Exécuteurs (runners)¶
Code source : Lib/asyncio/runners.py
Cette section décrit les primitives asyncio de haut niveau pour exécuter du code asynchrone.
Elles sont construites au-dessus d'une boucle d'événements dans le but de simplifier l'utilisation du code asynchrone pour les scénarios les plus courants.
Exécution d'un programme asynchrone¶
- asyncio.run(coro, *, debug=None)¶
Exécute la coroutine coro et renvoie le résultat.
This function runs the passed coroutine, taking care of managing the asyncio event loop, finalizing asynchronous generators, and closing the threadpool.
Cette fonction ne peut pas être appelée lorsqu'une autre boucle d'événement asynchrone est en cours d'exécution dans le même fil d'exécution.
Si debug vaut
True, la boucle d'événements est exécutée en mode débogage.Falsedésactive explicitement le mode débogage.Noneest utilisée pour respecter les paramètres globaux définis par Mode débogage.Cette fonction crée toujours une nouvelle boucle d'événements et la ferme à la fin. Elle doit être utilisée comme point d'entrée principal pour les programmes asynchrones et ne doit idéalement être appelée qu'une seule fois.
Exemple :
async def main(): await asyncio.sleep(1) print('hello') asyncio.run(main())
Nouveau dans la version 3.7.
Modifié dans la version 3.9: mise à jour pour utiliser
loop.shutdown_default_executor().Modifié dans la version 3.10: debug vaut
Nonepar défaut pour respecter les paramètres du mode de débogage global.
Gestionnaire de contexte de l'exécuteur¶
- class asyncio.Runner(*, debug=None, loop_factory=None)¶
Gestionnaire de contexte englobant plusieurs appels de fonctions asynchrones dans le même contexte.
Parfois, plusieurs fonctions asynchrones de niveau supérieur doivent être appelées dans la même boucle d'événements et le même
contextvars.Context.Si debug vaut
True, la boucle d'événements est exécutée en mode débogage.Falsedésactive explicitement le mode débogage.Noneest utilisée pour respecter les paramètres globaux définis par Mode débogage.loop_factory peut être utilisée pour remplacer la création de la boucle. loop_factory a la responsabilité de définir la boucle créée comme boucle courante. Par défaut
asyncio.new_event_loop()est utilisée et définie comme boucle d'événements actuelle avecasyncio.set_event_loop()si loop_factory vautNone.Fondamentalement, l'exemple
asyncio.run()peut être réécrit avec l'utilisation de l'exécuteur suivant :async def main(): await asyncio.sleep(1) print('hello') with asyncio.Runner() as runner: runner.run(main())
Nouveau dans la version 3.11.
- run(coro, *, context=None)¶
Exécute la coroutine coro dans la boucle d'événements en cours.
Renvoie le résultat de la coroutine ou lève les exceptions afférentes.
L'argument (uniquement nommé) facultatif context permet de spécifier un
contextvars.Contextpersonnalisé pour la coroutine à exécuter. Le contexte par défaut de l'exécuteur est utilisé si context estNone.Cette fonction ne peut pas être appelée lorsqu'une autre boucle d'événement asynchrone est en cours d'exécution dans le même fil d'exécution.
- close()¶
Termine l'exécuteur.
Finalise les générateurs asynchrones, arrête l'exécuteur par défaut, ferme la boucle d'événements et libère le
contextvars.Contexten cours.
- get_loop()¶
Renvoie la boucle d'événements associée à l'instance de l'exécuteur.
Note
Runnerutilise la stratégie d'initialisation paresseuse, son constructeur n'initialise pas les structures de bas niveau sous-jacentes.La boucle d'événements loop et le context intégrés sont créés à l'entrée du corps de
withou au premier appel derun()ouget_loop().
Gestion de l'interruption par le clavier¶
Nouveau dans la version 3.11.
Lorsque signal.SIGINT est déclenché par Ctrl-C, l'exception KeyboardInterrupt est levée par défaut dans le fils d'exécution principal. Cependant, cela ne fonctionne pas avec asyncio car cela peut interrompre le fonctionnement interne de asyncio et empêcher le programme de se terminer.
Pour contrer ce problème, asyncio gère signal.SIGINT comme suit :
asyncio.Runner.run()installe un gestionnairesignal.SIGINTpersonnalisé avant l'exécution de tout code utilisateur et le supprime à la sortie de la fonction.Le
Runnercrée la tâche principale pour la coroutine transmise pour son exécution.Lorsque
signal.SIGINTest déclenché par Ctrl-C, le gestionnaire de signal personnalisé annule la tâche principale en appelantasyncio.Task.cancel()qui lèveasyncio.CancelledErrorà l'intérieur de la tâche principale. Cela entraîne la remontée dans la pile Python, les blocstry/exceptettry/finallypeuvent être utilisés pour le nettoyage des ressources. Une fois la tâche principale annulée,asyncio.Runner.run()lèveKeyboardInterrupt.Un utilisateur peut écrire une boucle tellement petite qu'elle ne peut pas être interrompue par
asyncio.Task.cancel(); dans ce cas la seconde suivante Ctrl-C lève immédiatement leKeyboardInterruptsans annuler la tâche principale.