Infos réelles:
À partir de Python 3.7, asyncio.create_task(coro)
une fonction de haut niveau a été ajoutée à cet effet.
Vous devriez l'utiliser à la place d'autres façons de créer des tâches à partir de coroutimes. Cependant, si vous avez besoin de créer une tâche arbitraire, vous devez utiliser asyncio.ensure_future(obj)
.
Anciennes infos:
ensure_future
contre create_task
ensure_future
est une méthode pour créer à Task
partir de coroutine
. Il crée des tâches de différentes manières en fonction des arguments (y compris l'utilisation de create_task
pour les coroutines et les objets de type futur).
create_task
est une méthode abstraite de AbstractEventLoop
. Différentes boucles d'événements peuvent implémenter cette fonction de différentes manières.
Vous devez utiliser ensure_future
pour créer des tâches. Vous n'en aurez besoin create_task
que si vous allez implémenter votre propre type de boucle d'événement.
Actualiser:
@ bj0 a souligné la réponse de Guido sur ce sujet:
Le but de ensure_future()
est que si vous avez quelque chose qui pourrait être une coroutine ou un Future
(ce dernier inclut un Task
parce que c'est une sous-classe de Future
), et que vous voulez pouvoir appeler une méthode qui n'est définie que sur Future
(probablement à propos du seul exemple utile étant cancel()
). Quand c'est déjà un Future
(ou Task
) cela ne fait rien; quand c'est une coroutine, il l' enveloppe dans un Task
.
Si vous savez que vous avez une coroutine et que vous souhaitez qu'elle soit planifiée, l'API correcte à utiliser est create_task()
. Le seul moment où vous devriez appeler, ensure_future()
c'est lorsque vous fournissez une API (comme la plupart des API d'Asyncio) qui accepte soit une coroutine, soit une Future
et que vous devez faire quelque chose qui vous oblige à avoir un Future
.
et ensuite:
En fin de compte, je crois toujours que ensure_future()
c'est un nom assez obscur pour une fonctionnalité rarement nécessaire. Lors de la création d'une tâche à partir d'une coroutine, vous devez utiliser le fichier
loop.create_task()
. Peut-être qu'il devrait y avoir un alias pour ça
asyncio.create_task()
?
Cela me surprend. Ma principale motivation à utiliser depuis le ensure_future
début était que sa fonction de niveau supérieur était comparée au membre de la boucle create_task
(la discussion contient des idées telles que l'ajout asyncio.spawn
ou asyncio.create_task
).
Je peux également souligner qu'à mon avis, il est assez pratique d'utiliser une fonction universelle qui peut gérer n'importe quelles Awaitable
coroutines plutôt que des coroutines.
Cependant, la réponse de Guido est claire: "Lorsque vous créez une tâche à partir d'une coroutine, vous devez utiliser le nom approprié loop.create_task()
"
Quand les coroutines doivent-elles être enveloppées dans des tâches?
Envelopper la coroutine dans une tâche - est un moyen de démarrer cette coroutine "en arrière-plan". Voici un exemple:
import asyncio
async def msg(text):
await asyncio.sleep(0.1)
print(text)
async def long_operation():
print('long_operation started')
await asyncio.sleep(3)
print('long_operation finished')
async def main():
await msg('first')
# Now you want to start long_operation, but you don't want to wait it finised:
# long_operation should be started, but second msg should be printed immediately.
# Create task to do so:
task = asyncio.ensure_future(long_operation())
await msg('second')
# Now, when you want, you can await task finised:
await task
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Production:
first
long_operation started
second
long_operation finished
Vous pouvez remplacer asyncio.ensure_future(long_operation())
par juste await long_operation()
pour sentir la différence.
create_task
si vous avez vraiment besoin d'un objet de tâche, dont vous ne devriez normalement pas avoir besoin: github.com/python/asyncio/issues/477#issuecomment-268709555ensure_future
n'ajoute automatiquement crééTask
à la boucle d'événement?loop
argument mot-clé ( voir signature ensure_future ).await
intérieurmsg()
de rendre le contrôle à boucle d'événements sur le deuxième appel. Une fois la boucle d'événement reçue, le contrôle pourra démarrerlong_operation()
. Il a été conçu pour montrer commentensure_future
lance la coroutine pour s'exécuter simultanément avec le flux d'exécution actuel.create_task()
ensure_future()
create_task
,Comme vous pouvez le voir, create_task est plus spécifique.
async
fonction sans create_task ni ensure_futureLa
async
fonction d' appel simple renvoie la coroutineEt puisque le
gather
sous le capot assure (ensure_future
) que les arguments sont des futurs, ilensure_future
est explicitement redondant.Question similaire Quelle est la différence entre loop.create_task, asyncio.async / ensure_future et Task?
la source
À partir des documents officiels:
Détail:
Alors maintenant, à partir de Python 3.7, il existe 2 fonctions wrapper de premier niveau (similaires mais différentes):
asyncio.create_task
: qui appellent simplementevent_loop.create_task(coro)
directement. ( voir code source )ensure_future
qui appelle aussievent_loop.create_task(coro)
si c'est coroutine ou bien c'est simplement pour s'assurer que le type de retour est un asyncio.Future . ( voir le code source ). Quoi qu'il en soit,Task
c'est toujoursFuture
dû à son héritage de classe ( ref ).Eh bien, ces deux fonctions wrapper vous aideront à appeler
BaseEventLoop.create_task
. La seule différence est d'ensure_future
accepter n'importe quelawaitable
objet et de vous aider à le convertir en un futur. Et vous pouvez également fournir votre propreevent_loop
paramètre dansensure_future
. Et selon que vous avez besoin de ces fonctionnalités ou non, vous pouvez simplement choisir le wrapper à utiliser.la source
pour votre exemple, les trois types s'exécutent de manière asynchrone. la seule différence est que, dans le troisième exemple, vous avez pré-généré les 10 coroutines et soumis à la boucle ensemble. donc seul le dernier donne une sortie au hasard.
la source