如何获取异步任务中首个非None的结果并终止其他任务
如何在异步任务中获取首个非None结果并终止所有任务?
你的问题核心在于:asyncio.wait搭配FIRST_COMPLETED时,会把所有**执行完毕(无论返回None还是非None)**的任务都归为finished集合,哪怕任务返回的是None。要实现「只保留首个返回非None的任务,终止其余所有任务」的需求,可以改用asyncio.as_completed来逐个处理完成的任务,同时配合任务取消机制。
修改后的完整代码
import asyncio async def task_1(_id): _ids = ["230327-12717", "230221-28276", "230214-06090"] for i in _ids: if i == _id: return f"Found {_id} in task_1" async def task_2(_id): _ids = ["230502-14191", "230425-17005", "230327-14434"] for i in _ids: if i == _id: return f"Found {_id} in task_2" async def task_3(_id): _ids = ["230404-23786", "230221-25729", "230221-28276"] for i in _ids: if i == _id: return f"Found {_id} in task_3" async def main(_id): # 把协程包装成可取消的Task对象 tasks = [ asyncio.create_task(task_1(_id)), asyncio.create_task(task_2(_id)), asyncio.create_task(task_3(_id)) ] result_task = None try: # 逐个处理完成的任务 for done_task in asyncio.as_completed(tasks): result = await done_task if result is not None: # 找到目标结果,记录对应的任务 result_task = done_task # 取消所有未完成的任务 for task in tasks: if not task.done(): task.cancel() break finally: # 确保所有任务都被处理(忽略取消异常) for task in tasks: if not task.done(): try: await task except asyncio.CancelledError: pass if result_task: print({result_task}) if __name__ == "__main__": asyncio.run(main("230502-14191"))
关键逻辑说明
- 用
asyncio.create_task包装协程:只有Task对象支持取消操作,直接传入协程无法后续终止未完成的任务。 asyncio.as_completed遍历完成的任务:它会按任务完成的顺序返回可等待对象,我们可以逐个检查返回结果。- 找到非None结果后取消其余任务:一旦拿到非None的结果,立刻遍历所有任务,取消还在运行的任务,避免不必要的执行。
- 处理取消异常:取消任务会抛出
asyncio.CancelledError,需要在finally块中捕获并忽略,确保程序正常退出。
运行结果
执行后会输出你预期的内容:
{<Task finished name='Task-2' coro=<task_2() done, defined at /home/zerox/pipedrive_CRM/minimal.py:13> result='Found 230502-14191 in task_2'>}
内容的提问来源于stack exchange,提问作者X-something
相关产品推荐
相关产品推荐

