Python asyncio.gather() 与 wait() 的区别

asyncio.gather() 侧重收集有序结果并默认失败即止,返回按序列表;asyncio.wait() 侧重监控完成状态,返回(done, pending)元组,不保证顺序且需手动处理异常与结果。

asyncio.gather()asyncio.wait() 都用于并发执行多个协程,但设计目标、返回结果和错误处理方式不同:gather 更侧重“收集结果”,wait 更侧重“等待完成状态”。

返回值结构不同

gather 返回一个 按顺序排列的结果列表,对应传入协程的顺序。任一协程抛出异常,gather 默认立即传播(除非设置 return_exceptions=True)。

wait 返回一个 元组 (done, pending),其中 done 是已完成的 Task 集合(包含结果或异常),pending 是尚未完成的 Task 集合。它不保证顺序,也不自动整理结果。

  • gather(asyncio.sleep(1, result="a"), asyncio.sleep(0.5, result="b")) → ["a", "b"](顺序固定)
  • wait(...) → ({, }, set()),需手动遍历 done 获取结果

错误处理策略不同

gather 在默认模式下是“失败即止”:只要一个协程 raise 异常,整个 gather 调用就立刻报错,其余协程可能仍在运行(但通常会被取消)。

wait 则完全不干预异常——协程出错后仍算作“已完成”,异常会保留在对应

Task 的 exception() 中,由你自行检查和处理。

  • 用 gather 时想容错?加 return_exceptions=True,异常会以 Exception 实例形式出现在结果列表中
  • 用 wait 时需遍历 done 集合,对每个 task 调用 task.exception()task.result()

控制粒度与适用场景不同

gather 更适合“我有一组任务,要等它们全做完,并拿到所有返回值”的典型批量调用场景,语义清晰、代码简洁。

wait 提供更底层的控制能力,例如:

  • 只等前 N 个完成(用 return_when=asyncio.FIRST_COMPLETED
  • 等任意一个失败就退出(检查 done 中是否有异常 task)
  • 实现超时+取消逻辑(配合 timeout 参数和 pending 集合)

是否自动创建 Task 有差异

gather 会对非 Task 的协程对象自动调用 create_task()(或 ensure_future),你传协程就行。

wait 要求传入的必须是 Task 或 Future 对象;如果传协程,会报错。需要先用 asyncio.create_task() 包装。

  • gather(coro1, coro2) ✅ 可直接传协程
  • wait(coro1, coro2) ❌ 必须写成 wait(asyncio.create_task(coro1), asyncio.create_task(coro2))
简单说:要结果、要顺序、要省心,选 gather;要控制时机、要响应中间状态、要精细调度,选 wait。