Оновлено:
Замінити asyncio.ensure_future
з asyncio.create_task
всюди , якщо ви використовуєте Python> = 3,7 Це новий, гарний спосіб для спавна завдання .
asyncio. Завдання "пожежі та забуття"
Згідно з документами python для asyncio.Task
цього можна запустити якусь програму для виконання "у фоновому режимі" . Завдання, створене asyncio.ensure_future
функцією , не заблокує виконання (тому функція повернеться негайно!). Це виглядає як спосіб "стріляти і забути", як ви просили.
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())
Вихід:
Do some actions 1
async_foo started
Do some actions 2
async_foo done
Do some actions 3
Що робити, якщо завдання виконуються після завершення циклу подій?
Зауважте, що асинчіо очікує, що завдання буде виконане в момент завершення циклу подій. Тож якщо ви перейдете main()
на:
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')
Ви отримаєте це попередження після завершення програми:
Task was destroyed but it is pending!
task: <Task pending coro=<async_foo() running at [...]
Щоб запобігти тому, що ви можете просто очікувати всіх очікуваних завдань після завершення циклу подій:
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))
Вбивайте завдання, а не чекайте їх
Іноді не хочеться чекати виконання завдань (наприклад, деякі завдання можуть бути створені для запуску назавжди). У такому випадку ви можете просто скасувати їх (), а не чекати їх:
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)
Вихід:
Do some actions 1
echo
Do some actions 2
echo
Do some actions 3
echo