更新:
如果您使用 Python >= 3.7,请将 asyncio.ensure_future 替换为 asyncio.create_task,这是一种更新、更好的方式 to spawn tasks。
asyncio.Task 到“一劳永逸”
根据asyncio.Task 的python 文档,可以启动一些协程“在后台”执行。 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
如果事件循环完成后任务正在执行怎么办?
请注意,asyncio 期望在事件循环完成时完成任务。因此,如果您将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 [...]
为防止您在事件循环完成后只能await all pending tasks:
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)
输出:
Do some actions 1
echo
Do some actions 2
echo
Do some actions 3
echo