Stratégies¶
Une stratégie de boucle d'événements est un objet global, pour chaque processus, qui contrôle la gestion de la boucle d'événement. Chaque boucle d'événement a une stratégie par défaut, qui peut être modifiée et personnalisée à l'aide de l'API de la stratégie.
Une stratégie définit la notion de contexte et gère une boucle d'événement distincte par contexte. La stratégie par défaut définit le contexte comme étant le fil d'exécution actuel.
En utilisant une stratégie de boucle d'événement personnalisée, le comportement des fonctions get_event_loop()
, set_event_loop()
et new_event_loop()
peut être personnalisé.
Les objets de stratégie doivent implémenter les API définies dans la classe de base abstraite AbstractEventLoopPolicy
.
Obtenir et définir la stratégie¶
Les fonctions suivantes peuvent être utilisées pour obtenir et définir la stratégie du processus en cours :
-
asyncio.
get_event_loop_policy
()¶ Renvoie la stratégie actuelle à l'échelle du processus.
-
asyncio.
set_event_loop_policy
(policy)¶ Définit la stratégie actuelle sur l'ensemble du processus sur policy.
Si policy est définie sur
None
, la stratégie par défaut est restaurée.
Sujets de stratégie¶
La classe de base abstraite de la stratégie de boucle d'événements est définie comme suit:
-
class
asyncio.
AbstractEventLoopPolicy
¶ Une classe de base abstraite pour les stratégies asyncio.
-
get_event_loop
()¶ Récupère la boucle d'évènements pour le contexte actuel.
Renvoie un objet de boucle d'événements en implémentant l'interface
AbstractEventLoop
.Cette méthode ne devrait jamais renvoyer
None
.Modifié dans la version 3.6.
-
set_event_loop
(loop)¶ Définit la boucle d'événements du contexte actuel sur loop.
-
new_event_loop
()¶ Crée et renvoie un nouvel objet de boucle d'événements.
Cette méthode ne devrait jamais renvoyer
None
.
-
get_child_watcher
()¶ Récupère un objet observateur du processus enfant.
Renvoie un objet observateur implémentant l'interface
AbstractChildWatcher
.Cette fonction est spécifique à Unix.
-
set_child_watcher
(watcher)¶ Définit l'observateur du processus enfant actuel à watcher.
Cette fonction est spécifique à Unix.
-
asyncio est livré avec les stratégies intégrées suivantes :
-
class
asyncio.
DefaultEventLoopPolicy
¶ La stratégie asyncio par défaut. Utilise
SelectorEventLoop
sur les plates-formes Unix etProactorEventLoop
sur Windows.Il n'est pas nécessaire d'installer la stratégie par défaut manuellement. asyncio est configuré pour utiliser automatiquement la stratégie par défaut.
Modifié dans la version 3.8: On Windows,
ProactorEventLoop
is now used by default.
-
class
asyncio.
WindowsSelectorEventLoopPolicy
¶ Stratégie de boucle d'événements alternative utilisant l'implémentation de la boucle d'événements
ProactorEventLoop
.Disponibilité : Windows.
-
class
asyncio.
WindowsProactorEventLoopPolicy
¶ An alternative event loop policy that uses the
ProactorEventLoop
event loop implementation.Disponibilité : Windows.
Observateurs de processus¶
Un observateur de processus permet de personnaliser la manière dont une boucle d'événements surveille les processus enfants sous Unix. Plus précisément, la boucle d'événements a besoin de savoir quand un processus enfant s'est terminé.
Dans asyncio, les processus enfants sont créés avec les fonctions create_subprocess_exec()
et loop.subprocess_exec()
.
asyncio defines the AbstractChildWatcher
abstract base class, which child
watchers should implement, and has four different implementations:
ThreadedChildWatcher
(configured to be used by default),
MultiLoopChildWatcher
, SafeChildWatcher
, and
FastChildWatcher
.
Voir aussi la section sous-processus et fils d'exécution.
Les deux fonctions suivantes peuvent être utilisées pour personnaliser l'implémentation de l'observateur de processus enfant utilisé par la boucle d'événements asyncio :
-
asyncio.
get_child_watcher
()¶ Renvoie l'observateur enfant actuel pour la stratégie actuelle.
-
asyncio.
set_child_watcher
(watcher)¶ Définit l'observateur enfant actuel à watcher pour la stratégie actuelle. watcher doit implémenter les méthodes définies dans la classe de base
AbstractChildWatcher
.
Note
Les implémentations de boucles d'événement tierces peuvent ne pas prendre en charge les observateurs enfants personnalisés. Pour ces boucles d'événements, utiliser set_child_watcher()
pourrait être interdit ou n'avoir aucun effet.
-
class
asyncio.
AbstractChildWatcher
¶ -
add_child_handler
(pid, callback, *args)¶ Enregistre un nouveau gestionnaire.
Organise l'appel de
callback(pid, returncode, * args)
lorsqu'un processus dont le PID est égal à pid se termine. La spécification d'un autre rappel pour le même processus remplace le gestionnaire précédent.L'appelable callback doit être compatible avec les programmes à fils d'exécution multiples.
-
remove_child_handler
(pid)¶ Supprime le gestionnaire de processus avec un PID égal à pid.
La fonction renvoie
True
si le gestionnaire a été supprimé avec succès,False
s'il n'y a rien à supprimer.
-
attach_loop
(loop)¶ Attache l'observateur à une boucle d'événement.
Si l'observateur était précédemment attaché à une boucle d'événements, il est d'abord détaché avant d'être rattaché à la nouvelle boucle.
Remarque : la boucle peut être
None
.
-
is_active
()¶ Return
True
if the watcher is ready to use.Instancier un sous-processus avec un observateur enfant actuel inactif lève l'exception
RuntimeError
.Nouveau dans la version 3.8.
-
close
()¶ Ferme l'observateur.
Cette méthode doit être appelée pour s'assurer que les ressources sous-jacentes sont nettoyées.
-
-
class
asyncio.
ThreadedChildWatcher
¶ This implementation starts a new waiting thread for every subprocess spawn.
It works reliably even when the asyncio event loop is run in a non-main OS thread.
There is no noticeable overhead when handling a big number of children (O(1) each time a child terminates), but starting a thread per process requires extra memory.
This watcher is used by default.
Nouveau dans la version 3.8.
-
class
asyncio.
MultiLoopChildWatcher
¶ This implementation registers a
SIGCHLD
signal handler on instantiation. That can break third-party code that installs a custom handler forSIGCHLD
signal.The watcher avoids disrupting other code spawning processes by polling every process explicitly on a
SIGCHLD
signal.There is no limitation for running subprocesses from different threads once the watcher is installed.
The solution is safe but it has a significant overhead when handling a big number of processes (O(n) each time a
SIGCHLD
is received).Nouveau dans la version 3.8.
-
class
asyncio.
SafeChildWatcher
¶ This implementation uses active event loop from the main thread to handle
SIGCHLD
signal. If the main thread has no running event loop another thread cannot spawn a subprocess (RuntimeError
is raised).The watcher avoids disrupting other code spawning processes by polling every process explicitly on a
SIGCHLD
signal.This solution is as safe as
MultiLoopChildWatcher
and has the same O(N) complexity but requires a running event loop in the main thread to work.
-
class
asyncio.
FastChildWatcher
¶ Cette implémentation récupère tous les processus terminés en appelant directement
os.waitpid(-1)
, cassant éventuellement un autre code qui génère des processus et attend leur fin.Il n'y a pas de surcharge visible lors de la manipulation d'un grand nombre d'enfants (O(1) à chaque fois qu'un enfant se termine).
This solution requires a running event loop in the main thread to work, as
SafeChildWatcher
.
-
class
asyncio.
PidfdChildWatcher
¶ This implementation polls process file descriptors (pidfds) to await child process termination. In some respects,
PidfdChildWatcher
is a "Goldilocks" child watcher implementation. It doesn't require signals or threads, doesn't interfere with any processes launched outside the event loop, and scales linearly with the number of subprocesses launched by the event loop. The main disadvantage is that pidfds are specific to Linux, and only work on recent (5.3+) kernels.Nouveau dans la version 3.9.
Stratégies personnalisées¶
Pour implémenter une nouvelle politique de boucle d’événements, il est recommandé de sous-classer DefaultEventLoopPolicy
et de réimplémenter les méthodes pour lesquelles un comportement personnalisé est souhaité, par exemple :
class MyEventLoopPolicy(asyncio.DefaultEventLoopPolicy):
def get_event_loop(self):
"""Get the event loop.
This may be None or an instance of EventLoop.
"""
loop = super().get_event_loop()
# Do something with loop ...
return loop
asyncio.set_event_loop_policy(MyEventLoopPolicy())