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-268709555