2017-10-19 9 views
1

Je pense que je reçois cette erreur car mon code appelle asyncio.get_event_loop().run_until_complete(foo()) deux fois. Une fois de foo() et la deuxième fois de la fonction appelée par foo(). Ma question est alors: pourquoi cela devrait-il être un problème? Pourquoi devrais-je même m'inquiéter que cette boucle fonctionne?RuntimeError: Cette boucle d'événement est déjà en cours d'exécution en python


Il y avait une modification apportée à cette question, je pense, obscurcie (certaines personnes préfèrent suivre les règles sans les comprendre, donc un mot « illégal » a été retiré du titre). Malheureusement, cela crée de la confusion.

Je ne suis pas surpris par le fait que l'erreur est élevée. Je peux remonter à la source asyncio et voir que les auteurs de cette bibliothèque voulaient le faire de cette façon, il n'y a pas de mystère là-bas. La partie embarrassante est dans la raison pour laquelle les auteurs de la bibliothèque ont décidé qu'il est illégal de demander à la boucle d'événements d'exécuter certaines fonctions jusqu'à la fin lorsque la boucle est déjà en cours d'exécution.

Nous pouvons réduire le problème à seulement deux de ces appels, et par l'analyse de cas, nous verrons que ce sont les trois possibilités:

  1. Aucune des deux fonctions se termine jamais.
  2. L'une des fonctions se termine éventuellement.
  3. Les deux fonctions finissent par se terminer.

Maintenant, y a-t-il un comportement sain qui répondrait aux trois cas? Pour moi, il est évident qu'il y a, ou peut-être, des comportements multiples possibles ici. Par exemple:

  1. Rien de spécial, l'exécution des deux fonctions est entrelacée, et ils continuent à fonctionner pour toujours, comme prévu.
  2. La boucle ne retourne pas le contrôle au code suivant la première instance de run_until_complete() jusqu'à ce que deuxième fonction complète (donc pas de code après run_until_complete() sera exécuté.
  3. Après la dernière fonction se termine, le retour de la boucle de contrôle au premier code objet invoqué run_until_complete en ignorant tous les autres sites d'invocation.

maintenant, je peux comprendre que ce comportement ne peut pas être quelque chose que tout le monde voudrait. Mais, étant donné que cette bibliothèque a décidé de donner aux programmeurs le contrôle de démarrage/arrêt de la boucle d'événements , il devrait également faire face aux conséquences de telles décisions. boucle plusieurs fois empêche le code de la bibliothèque de le faire, ce qui réduit la qualité et l'utilité des bibliothèques en utilisant asyncio (ce qui est en effet le cas avec, par exemple, aiohttp).

Répondre

2

Boucle d'événement en cours d'exécution - est un point d'entrée de votre programme asynchrone. Il gère l'exécution de toutes les coroutines, tâches, rappels. L'exécution de la boucle pendant son exécution n'a aucun sens: en quelque sorte, c'est comme essayer d'exécuter l'exécuteur de travaux à partir du même exécuteur de travaux déjà en cours d'exécution.

Puisque vous avez cette question, je suppose que vous pouvez vous méprendre sur le fonctionnement de l'asyncio. S'il vous plaît, lisez this article - ce n'est pas grand et donne une bonne introduction.

Upd:

Il n'y a absolument aucun problème à ajouter plusieurs choses à être exécuté par boucle d'événement alors que cette boucle est déjà en cours d'exécution. Vous pouvez le faire simplement en attente pour elle:

await coro() # add coro() to be run by event loop blocking flow here until coro() is finished 

ou la création d'une tâche:

asyncio.ensure_future(coro()) # add coro() to be run by event loop without blocking flow here 

Comme vous pouvez le voir ne pas besoin de méthodes de boucle d'événement d'appel pour faire quelque chose d'être couru par elle.

La méthode de la boucle d'événements, telle que run_forever ou run_until_complete - est simplement un moyen de démarrer la boucle d'événements en général. Signifie: "ajouter foo() pour être exécuté par la boucle d'événements et exécuter la boucle d'événement elle-même jusqu'à ce que foo() ne soit pas terminé".

+0

... mais je ne lance pas la boucle d'événements, je cours 'foo()' pourquoi ai-je même besoin d'exécuter la boucle explicitement? Qui sur Terre voudrait * ça *? C'est comme déplacer les aiguilles de votre horloge murale avec vos mains ... pour faire avancer le temps ... – wvxvw

+0

Re 'article - merci. Je vais le lire maintenant. Comparé à tout langage qui met la concomitance dans sa conception dès le départ, 'asyncio' est si mauvais, à tellement de niveaux ... qu'il semble au-delà de la rédemption. Tout est mauvais, le design, l'implémentation, la documentation ... Python était globalement un langage correct, mais cet ajout ... je ne sais même pas comment le décrire. – wvxvw

+0

Eh bien, l'article est très superficiel, avec quelques exemples de niveau hello-world qui ne retiennent pas l'eau lorsqu'il est appliqué à quelque chose de plus réaliste ...:/ – wvxvw