3 Réponses :
Votre compréhension de await est correcte. Cela met en pause l'exécution de la fonction principale.
La clé est que asyncio.create_task ()
crée une tâche et la planifie.
La fonction say_after
démarre ici:
task1 = asyncio.create_task( say_after(1, 'hello')) task2 = asyncio.create_task( say_after(2, 'world'))
et non lorsque vous attendez.
Voir ici: https://docs.python.org/3 /library/asyncio-task.html#asyncio.create_task
eh bien oui, je sais que c'est la tâche, mais ça semble bizarre que wait
change son comportement si c'est une tâche?
Pourriez-vous clarifier comment vous pensez que cela change de comportement? await
fait attendre le retour de la fonction asynchrone say_after
.
la coroutine ne démarre pas avant wait task1
, donc ce n'est pas comme thread.join
Il commence à asyncio.create_task (say_after (1, 'hello'))
, lorsque la tâche est créée. essayez d'exécuter le code sans les lignes wait
, vous constaterez que le programme imprime encore hello world
.
Jetez un œil à ma dernière mise à jour, elle imprime Mot reçu
après l'impression de Horodatage de démarrage
La fonction say_after
ne démarre pas à create_task
, elle démarre à l'entrée suivante dans la boucle d'événements. C'est ce qui se passe (généralement) à la prochaine attente
, indépendamment de ce qui est attendu.
Lorsque vous encapsulez une coroutine dans un objet Task (ou Future), la coroutine est prête à fonctionner, donc lorsque la boucle d'événements commence à s'exécuter lors de la première attente, la tâche1 et la tâche2 sont en cours d'exécution.
Pour clarifier les choses, pour exécuter une coroutine, vous avez besoin de deux choses:
1) une coroutine incapsulée dans un futur objet (Task) pour la rendre attendu
2) une boucle d'événement en cours
Dans votre exemple, l'exécution fonctionne comme ceci:
1 - create_task1
2 - create_task2
3 - attendre la tâche1
4 - attendre le sommeil de la tâche1
5 - attendre le sommeil de la tâche2
maintenant, la tâche1 et la tâche2 sont en veille, donc, supposons que la tâche1 soit la première à terminer (dormir quelque temps)
6 - impression de la tâche1
7 - attendre la tâche2
8 - impression de la tâche2
maintenant la boucle se termine
Comme vous l'avez dit lorsque vous avez une attente, l'exécution s'arrête, mais laissez-moi vous dire que cela s'arrête juste dans le "flux d'exécution" actuel, lorsque vous créez une future (tâche), vous créez un autre flux d'exucution, et l'attente passe simplement à le flux d'exécution actuel. Cette dernière explication n'est pas tout à fait correcte dans le sens des termes mais aide à la rendre plus claire.
J'espère avoir été clair. P.S .: désolé pour mon mauvais anglais.
create_task ()
ne démarre pas la coroutine immédiatement, elle ne démarre que jusqu'à wait task1
, mais je crois comprendre que awake task1
devrait bloquer l'exécution de attendez la tâche2
jusqu'à ce que la tâche1
soit terminée.
Je pense que votre compréhension est correcte mais juste du point de vue de la fonction qui appelle l'attente, d'un point de vue global l'attente, il suffit de passer l'exécution à une autre tâche, c'est pourquoi le multitâche avec coroutine est coopératif et non préventif.
Je ne peux tout simplement pas faire passer le fait que les blocs wait task1
commencent à exécuter wait task2
, si wait task2
n'est pas exécuté dans le contexte de la fonction actuelle, alors comment peut task2
s'exécuter simultanément avec task1
.
OK Les réponses @tsuyoku et @Fanto sont correctes, cette réponse est juste pour compléter les réponses existantes, le point important pour moi que je ne pouvais pas saisir était l'exécution commencée sur create_task ()
:
started at 10:42:10 Received hello Received world hello world task 2 finished task 1 finished finished at 10:42:20
prints
import asyncio import time async def say_after(delay, what): print('Received {}'.format(what)) await asyncio.sleep(delay) print(what) async def main(): task1 = asyncio.create_task( say_after(1, 'hello') ) task2 = asyncio.create_task( say_after(2, 'world') ) print(f"started at {time.strftime('%X')}") await asyncio.sleep(10) # Wait until both tasks are completed (should take # around 2 seconds.) await task2 print('task 2 finished') await task1 print('task 1 finished') print(f"finished at {time.strftime('%X')}") asyncio.run(main())
le malentendu original est que les choses prennent un peu de temps pour exécuter les tâches, et l'impression originale dans mon La question m'a induit en erreur en pensant que la tâche ne s'exécute pas avant l'instruction wait
.