You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取异步任务中首个非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"))

关键逻辑说明

  1. 用asyncio.create_task包装协程:只有Task对象支持取消操作,直接传入协程无法后续终止未完成的任务。
  2. asyncio.as_completed遍历完成的任务:它会按任务完成的顺序返回可等待对象,我们可以逐个检查返回结果。
  3. 找到非None结果后取消其余任务:一旦拿到非None的结果,立刻遍历所有任务,取消还在运行的任务,避免不必要的执行。
  4. 处理取消异常:取消任务会抛出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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 01:38:37