Ce document est relatif à une vieille version de Python qui n'est plus soutenue. Mettez à jour votre version et lisez Bienvenue sur la documentation de la version stable actuelle de Python.

# 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 et 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.

class `asyncio.``WindowsProactorEventLoopPolicy`

  Stratégie 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 de base abstraite `AbstractChildWatcher`, que les observateurs enfants doivent implémenter et possède deux implémentations différentes : `SafeChildWatcher` (configurée pour être utilisé par défaut) 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 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`.

  `close`()

    Ferme l'observateur.

    Cette méthode doit être appelée pour s'assurer que les ressources sous-jacentes sont nettoyées.

class `asyncio.``SafeChildWatcher`

  Cette implémentation évite de perturber un autre code qui aurait besoin de générer des processus en interrogeant chaque processus explicitement par un signal `SIGCHLD`.

  C'est une solution sûre, mais elle nécessite un temps système important lors de la manipulation d'un grand nombre de processus (O(n) à chaque fois que un `SIGCHLD` est reçu).

  asyncio utilise cette implémentation sécurisée par défaut.

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).

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