更新:
如果您正在使用Python >= 3.7,请将asyncio.ensure_future
替换为asyncio.create_task
,这是一种更新、更好的生成任务的方式。
asyncio.Task实现“启动并忘记”
根据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())
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
如果任务在事件循环完成后执行怎么办?
请注意,asyncio希望任务在事件循环完成时被完成。因此,如果您将main()
更改为:
async def main():
asyncio.ensure_future(async_foo())
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())
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())
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())
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())
pending = asyncio.Task.all_tasks()
for task in pending:
task.cancel()
with suppress(asyncio.CancelledError):
loop.run_until_complete(task)
输出:
Do some actions 1
echo
Do some actions 2
echo
Do some actions 3
echo