Actualiser:
Remplacez asyncio.ensure_future
par asyncio.create_task
partout si vous utilisez Python> = 3.7 C'est un moyen plus récent et plus agréable de générer une tâche .
asyncio.Tâche de "tirer et oublier"
Selon la documentation de python, asyncio.Task
il est possible de démarrer une coroutine à exécuter "en arrière-plan" . La tâche créée par asyncio.ensure_future
function ne bloquera pas l'exécution (donc la fonction retournera immédiatement!). Cela ressemble à un moyen de «tirer et d'oublier» comme vous l'avez demandé.
import asyncio
async def async_foo():
print("async_foo started")
await asyncio.sleep(1)
print("async_foo done")
async def main():
asyncio.ensure_future(async_foo()) # fire and forget async_foo()
# btw, you can also create tasks inside non-async funcs
print('Do some actions 1')
await asyncio.sleep(1)
print('Do some actions 2')
await asyncio.sleep(1)
print('Do some actions 3')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Production:
Do some actions 1
async_foo started
Do some actions 2
async_foo done
Do some actions 3
Que faire si les tâches s'exécutent après la fin de la boucle d'événements?
Notez qu'asyncio s'attend à ce que la tâche soit terminée au moment où la boucle d'événements est terminée. Donc, si vous changez main()
pour:
async def main():
asyncio.ensure_future(async_foo()) # fire and forget
print('Do some actions 1')
await asyncio.sleep(0.1)
print('Do some actions 2')
Vous recevrez cet avertissement une fois le programme terminé:
Task was destroyed but it is pending!
task: <Task pending coro=<async_foo() running at [...]
Pour éviter cela, vous pouvez simplement attendre toutes les tâches en attente une fois la boucle d'événements terminée:
async def main():
asyncio.ensure_future(async_foo()) # fire and forget
print('Do some actions 1')
await asyncio.sleep(0.1)
print('Do some actions 2')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
# Let's also finish all running tasks:
pending = asyncio.Task.all_tasks()
loop.run_until_complete(asyncio.gather(*pending))
Tuez les tâches au lieu de les attendre
Parfois, vous ne voulez pas attendre que les tâches soient terminées (par exemple, certaines tâches peuvent être créées pour s'exécuter indéfiniment). Dans ce cas, vous pouvez simplement les annuler () au lieu de les attendre:
import asyncio
from contextlib import suppress
async def echo_forever():
while True:
print("echo")
await asyncio.sleep(1)
async def main():
asyncio.ensure_future(echo_forever()) # fire and forget
print('Do some actions 1')
await asyncio.sleep(1)
print('Do some actions 2')
await asyncio.sleep(1)
print('Do some actions 3')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
# Let's also cancel all running tasks:
pending = asyncio.Task.all_tasks()
for task in pending:
task.cancel()
# Now we should await task to execute it's cancellation.
# Cancelled task raises asyncio.CancelledError that we can suppress:
with suppress(asyncio.CancelledError):
loop.run_until_complete(task)
Production:
Do some actions 1
echo
Do some actions 2
echo
Do some actions 3
echo