Gestion du lancement des tâches asynchrones dans aiodemo

Bonjour,

Suite au post suivant :

je revois petit à petit le code de MyModbus bêta.

Dans le cas de MyModbus, aujourd’hui, un multiprocessing.Process() est lancé pour chaque équipement afin de le rendre indépendant des autres. Il est donc possible de gérer ces process (les lister, les stopper, en créer d’autres) ce qui permet la gestion de l’activation/désactivation des équipements.
Dans l’exemple, les tâches sont définies dans main() et à la fin asyncio.gather() attend la fin de l’exécution des tâches. Pour l’exemple ça marche bien puisqu’il n’y a qu’une seule tâche définie et il n’y en aura pas d’autres. Pour MyModbus, j’imagine que dans l’équivalent de main() les fonctions de communication soient créées et lancées et que la première chose que Publisher fait après le teste de communication est de demander la configuration du plugin et de lancer une tâche par équipement lors de la réception de cette liste.
Je pense sauvegarder une référence pour chaque tâche dans une liste ou un dict afin de pouvoir interroger les tâches et les manipuler. Est-ce que c’est la bonne façon de faire ou est-ce qu’il faudrait faire autrement ? asyncio.alltasks() serait une alternative.
Avec run_until_complete() ?
→ je pense commencer comme ça

J’ai aussi pensé à faire comme proposé dans cet article (l’exemple avec ProcessPoolExecutor() ) mais je n’ai pas encore commencé/essayé.

Bref, beaucoup de questions portant sur la gestion de base.

Vous savez quelle est la méthode adéquate ? Laquelle il faudrait fuir ? En serait-ce une autre (ce qui est tout à fait possible) ? Vous avez des conseils ?

A+
Michel

Salut,

Je ne pense pas qu’il y ai une méthode miracle à toujours appliquer, ca va dépendre des besoins.

quelques retours dans le désordre:

Sur certains plugins j’ai un dict avec mes tâches car c’est assez statique ce que je créé donc gérable ainsi.
Sur d’autres, c’est beaucoup plus dynamique (ca dépend de ce qui est en cours) et du coup je suis passé par asyncio.all_tasks() pour les récupérer à la fin et tout annuler.

Tu ne peux pas avoir deux run de loop, donc le run_until_complete() tu dois le faire à la place du run sur main du coup (je ne sais pas si c’était clair pour toi donc je préfère préciser)

tu peux regarder le code de GitHub - Mips2648/jeedom-kroomba: kroomba is a Jeedom plugin for control Roomba 980 si tu veux, j’ai plutôt pris ce principe là dans ce plugin.

Bonjour,

Pour ma part, pour un plugin sur lequel je planche en ce moment, j’utilise une liste globale dans laquelle j’ajoute les « task » au fur et à mesure où j’en ai besoin.

Donc au départ, il n’y a que le « publisher » et le « listen », et une task « mainLoop », et j’ai aussi une variable qui représente la loop asyncio actuelle et en l’appelant j’ajoute les tâches (create_task) et je lance un asyncio.gather(*ma_liste_de_tâches) à chaque fois, comme ca à la fin, les cancel (à l’arrêt du démon) sont appelés tous par la boucle principale asyncio.

Je ne sais pas si c’est la bonne méthode, mais ca a l’air de répondre à mon besoin pour l’instant (je n’en suis qu’au début de l’implémentation)

TiTidom.

Salut,

En regardant ce plugin, j’ai vu que les appels asyncio (via self.loop) étaient faits avec create_task(), run_in_executor() ou call_soon_threadsafe(). Tu peux m’expliquer les nuances STP ?

En bref, non les 3 ne font pas du tout à la même chose:

  • create_task sert à créer une tache (= « appeler » une methode async) depuis une qui ne l’est pas (sinon on fait juste un await xxx)
  • run_in_executor permet un peu l’inverse: appeler une fonction potentiellement bloquante (qui n’est pas async/await) depuis une tache async (et donc sans la bloquer); ca créé un thread en fait; donc on « perd » le concept asyncio mais c’est nécessaire lorsqu’on utilise du code qu’on ne contrôle pas (client mqtt ici)
  • call_soon_threadsafe permet depuis un callback (ici on_connect du client mqtt), d’appeler une méthode de façon sur car normalement la loop gère l’exécution de tout le code (avec les interuptions etc) mais un callback appelé depuis un autre thread va arriver n’importe quand

pour plus de détails je te laisse la doc de asyncio :wink:

1 « J'aime »

Merci pour ce résumé déjà très explicite. Je me suis lancé dans le visionnage de plusieurs heures de formation sur asyncio, mais ça me permet d’avoir une bonne intro.