asyncio.gather()并发执行多个awaitable并按序返回结果,任一失败则整体失败;加return_exceptions=true可捕获异常为返回值,需确保参数均为awaitable,避免同步阻塞或协程对象误传。

asyncio.gather() 就是 Python 的 Promise.all
它能并发执行多个 awaitable,并按传入顺序返回结果;任一失败则整体失败(和 Promise.all() 行为一致)。别用 asyncio.wait() 或手动 create_task() + await 列表——那是绕远路。
-
asyncio.gather()默认不抑制异常:一个协程抛出Exception,整个调用立即 raise,其余仍在运行但结果被丢弃 - 想“全部执行完、不管成败”,加参数
return_exceptions=True,此时失败项返回的是Exception实例而非抛出 - 传入的 awaitable 不会自动包装成 task,所以如果某个协程耗时长又没被其他地方引用,可能被 GC 掉(极少见,但需知道)
常见错误:把普通函数或同步代码直接塞进 gather
比如写 asyncio.gather(time.sleep(1), fetch_data()) ——time.sleep() 是同步阻塞,会卡住整个 event loop;fetch_data() 如果没加 await,传进去的是协程对象(coroutine object),不是 awaitable 的执行结果。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 同步操作必须用
loop.run_in_executor()包一层,例如:loop.run_in_executor(None, time.sleep, 1) - 确保每个参数都是 awaitable:要么是协程调用(如
fetch_data()),要么是已创建的Task或Future - 别写
gather([coro1(), coro2()])——gather接收 *args,不是 list;正确写法是gather(coro1(), coro2())
和 Promise.allSettled() 对应的写法
JavaScript 的 Promise.allSettled() 总是返回每个任务的状态(fulfilled/rejected),Python 没内置等价物,但用 gather(return_exceptions=True) 加一层类型判断就能模拟。
results = await asyncio.gather(
coro1(),
coro2(),
return_exceptions=True
)
for r in results:
if isinstance(r, Exception):
print(f"failed: {r}")
else:
print(f"success: {r}")
- 注意:
return_exceptions=True不会阻止异常传播到gather返回值里,只是把它变成普通返回值 - 不要在
except里吞掉所有异常再 return None——这会丢失错误类型和 traceback,调试困难 - 如果需要区分异常类型(比如只忽略
TimeoutError),得在循环里用isinstance(r, TimeoutError)判断
性能与调度细节容易被忽略
gather() 内部会把每个 awaitable 包装成 Task 并发调度,但不会做任何优先级控制或取消传播。如果你传入的是已经 asyncio.create_task() 过的 task,它们的生命周期就脱离了 gather 管理——即使 gather 因异常退出,那些 task 仍继续运行。
- 需要超时控制?直接包在
asyncio.wait_for(gather(...), timeout=5)里,别给每个子协程单独加wait_for - 需要可取消?确保传入的是协程调用(非已启动 task),否则 cancel 无效
- 大量并发(比如上千个请求)时,
gather本身开销不大,但要注意连接池、文件描述符、内存占用——这些限制不在gather职责范围内
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










