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

为何在asyncio.gather中使用asyncio.ensure_future?直接传协程可行吗?

直接传协程 vs 提前用asyncio.ensure_future包装

先给结论:在你给出的场景里,额外调用asyncio.ensure_future没有明显优势,直接传协程的写法更简洁,完全够用。

下面具体拆解两者的区别和ensure_future的适用场景:

  • asyncio.gather本身就会自动把传入的协程对象包装成Task(等同于调用ensure_future或create_task),所以第一种写法里,gather内部已经帮你完成了协程转Task的操作,最终的并发执行逻辑和第二种写法完全一致。

那什么时候需要提前用ensure_future呢?只有当你需要在调用gather之前,对任务做额外操作的时候:

  • 提前启动任务:如果生成任务列表后,你还有其他耗时的异步/同步操作要做,提前把协程转成Task的话,这些任务会立刻进入事件循环开始执行,不用等你调用await gather。比如:

    async def get_resources():
        async with aiohttp.ClientSession(base_url=BASE_URL) as session:
            # 提前创建Task,任务立刻开始执行
            tasks = [asyncio.ensure_future(fetch(session, res)) for res in resources]
            # 这里做一些其他操作,比如读取本地文件、计算参数等
            await do_something_else()
            # 等所有任务完成
            return await asyncio.gather(*tasks)
    

    这种情况下,任务在do_something_else执行的时候已经在并发跑了,能节省整体耗时。

  • 单独操作任务:如果需要跟踪单个任务的状态(比如判断是否完成task.done())、给任务添加回调函数(task.add_done_callback(...)),或者手动取消任务(task.cancel()),就必须把协程转成Task对象,这时候就需要用ensure_future(Python3.7+更推荐用asyncio.create_task,它是ensure_future的简化版,专门用于创建协程的Task)。

  • 处理非协程的Future对象:ensure_future还能接受Future对象(比如第三方库返回的Future),而gather虽然也能处理,但如果你需要统一处理协程和Future,ensure_future可以帮你做类型统一。

回到你的代码,因为生成任务列表后立刻就await gather,没有中间操作,所以两种写法效果完全一样,直接传协程更简洁,没必要多此一举。

内容的提问来源于stack exchange,提问作者adrian oviedo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 03:21:01