Upd:
Replace asyncio.ensure_future
with asyncio.create_task
如果你使用 Python >= 3.7 则到处都是 这是一种更新、更好的方法产生任务 https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task.
asyncio.Task“一劳永逸”
根据 python 文档asyncio.Task https://docs.python.org/3/library/asyncio-task.html#asyncio.Task可以启动一些协程“在后台”执行。创建的任务asyncio.ensure_future https://docs.python.org/3/library/asyncio-future.html#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())
Output:
Do some actions 1
async_foo started
Do some actions 2
async_foo done
Do some actions 3
如果任务在事件循环完成后执行怎么办?
请注意,asyncio 期望任务在事件循环完成时完成。所以如果你愿意改变main()
to:
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 [...]
为了防止这种情况,你可以等待所有待处理的任务 https://stackoverflow.com/a/27910822/1113207事件循环完成后:
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))
杀死任务而不是等待它们
有时您不想等待任务完成(例如,某些任务可能会创建为永远运行)。在这种情况下,您只需cancel()
他们而不是等待他们:
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)
Output:
Do some actions 1
echo
Do some actions 2
echo
Do some actions 3
echo