Politiques

Une politique de boucle d'événements est un objet global utilisé pour obtenir et définir la boucle d'événements actuelle, ainsi que créer de nouvelles boucles d'événements. La politique par défaut peut être remplacée par des alternatives intégrées afin d'utiliser d'autres implémentations de boucles d'événements, ou remplacée par une politique personnalisée qui peut remplacer ces comportements.

Un objet politique définit la notion de contexte et gère une boucle d'événement distincte par contexte. Ceci est valable fil par fil d'exécution par défaut, bien que les politiques personnalisées puissent définir le contexte différemment.

En utilisant une politique 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 politiques doivent implémenter les API définies dans la classe mère abstraite AbstractEventLoopPolicy.

Obtenir et définir la politique

Les fonctions suivantes peuvent être utilisées pour obtenir et définir la politique du processus en cours :

asyncio.get_event_loop_policy()

Renvoie la politique actuelle à l'échelle du processus.

asyncio.set_event_loop_policy(policy)

Définit la politique actuelle sur l'ensemble du processus sur policy.

Si policy est définie sur None, la politique par défaut est restaurée.

Objets politiques

La classe mère abstraite de la politique de boucle d'événements est définie comme suit :

class asyncio.AbstractEventLoopPolicy

Une classe de base abstraite pour les politiques 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.

Obsolète depuis la version 3.12.

set_child_watcher(watcher)

Définit l'observateur du processus enfant actuel à watcher.

Cette fonction est spécifique à Unix.

Obsolète depuis la version 3.12.

asyncio est livré avec les politiques intégrées suivantes :

class asyncio.DefaultEventLoopPolicy

La politique asyncio par défaut. Utilise SelectorEventLoop sur les plates-formes Unix et ProactorEventLoop sur Windows.

Il n'est pas nécessaire d'installer la politique par défaut manuellement. asyncio est configuré pour utiliser automatiquement la politique par défaut.

Modifié dans la version 3.8: Sous Windows, ProactorEventLoop est désormais utilisée par défaut.

Obsolète depuis la version 3.12: The get_event_loop() method of the default asyncio policy now emits a DeprecationWarning if there is no current event loop set and it decides to create one. In some future Python release this will become an error.

class asyncio.WindowsSelectorEventLoopPolicy

Politique de boucle d'événements alternative utilisant l'implémentation de la boucle d'événements ProactorEventLoop.

Disponibilité : Windows.

class asyncio.WindowsProactorEventLoopPolicy

Politique de boucle d'événements alternative utilisant l'implémentation de la boucle d'événements ProactorEventLoop.

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 définit la classe mère abstraite AbstractChildWatcher, que les observateurs enfants doivent implémenter et possède quatre implémentations différentes : ThreadedChildWatcher (configurée pour être utilisé par défaut), MultiLoopChildWatcher, SafeChildWatcher et 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 politique actuelle.

Obsolète depuis la version 3.12.

asyncio.set_child_watcher(watcher)

Définit l'observateur enfant actuel à watcher pour la politique actuelle. watcher doit implémenter les méthodes définies dans la classe de base AbstractChildWatcher.

Obsolète depuis la version 3.12.

Note

Les implémentations de boucles d'événements 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()

Renvoie True si l'observateur est prêt à être utilisé.

La création d'un sous-processus avec un observateur enfant actuel inactif lève une 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.

Obsolète depuis la version 3.12.

class asyncio.ThreadedChildWatcher

Cette implémentation démarre un nouveau fil d'exécution en attente pour chaque génération de sous-processus.

Il fonctionne de manière fiable même lorsque la boucle d'événements asyncio est exécutée dans un fil d'exécution non principal.

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.

Cet observateur est utilisé par défaut.

Nouveau dans la version 3.8.

class asyncio.MultiLoopChildWatcher

Cette implémentation enregistre un gestionnaire de signal SIGCHLD lors de l'instanciation. Cela peut casser le code tiers qui installe un gestionnaire personnalisé pour le signal SIGCHLD.

L'observateur évite de perturber un autre code qui crée des processus en interrogeant explicitement chaque processus sur un signal SIGCHLD.

Il n'y a aucune limitation pour l'exécution de sous-processus à partir de différents fils d'exécution une fois l'observateur installé.

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.

Obsolète depuis la version 3.12.

class asyncio.SafeChildWatcher

Cette implémentation utilise une boucle d'événements active du fil d'exécution principal pour gérer le signal SIGCHLD. Si le fil d'exécution principal n'a pas de boucle d'événements en cours d'exécution, un autre fil ne pourra pas générer de sous-processus (une RuntimeError est levée).

L'observateur évite de perturber un autre code qui crée des processus en interrogeant explicitement chaque processus sur un signal SIGCHLD.

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.

Obsolète depuis la version 3.12.

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.

There is no noticeable overhead when handling a big number of children (O(1) each time a child terminates).

Cette solution nécessite une boucle d'événements en cours d'exécution dans le fil d'exécution principal pour fonctionner, comme SafeChildWatcher.

Obsolète depuis la version 3.12.

class asyncio.PidfdChildWatcher

Cette implémentation interroge les descripteurs de fichiers de processus (pidfds) pour attendre la fin du processus enfant. À certains égards, PidfdChildWatcher est une implémentation d'observateur d'enfants Goldilocks. Elle ne nécessite ni signaux ni threads, n'interfère avec aucun processus lancé en dehors de la boucle d'événements et évolue de manière linéaire avec le nombre de sous-processus lancés par la boucle d'événements. Le principal inconvénient est que les pidfds sont spécifiques à Linux et ne fonctionnent que sur les noyaux récents (5.3+).

Nouveau dans la version 3.9.

Politiques 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())