Python异步IO:await asyncio.gather与create_task+wait的概念差异
Python异步IO:gather与wait的差异及事件循环写法解析
首先要明确:你看到的两种写法,核心差异是asyncio API的新旧风格,同时也涉及asyncio.gather和asyncio.wait这两个API的定位区别。
一、事件循环写法的新旧区别
现代async/await风格(Python 3.7+推荐)
不需要手动获取和管理事件循环,直接用asyncio.create_task创建任务,配合await等待任务完成:await asyncio.gather( asyncio.create_task(task("One", work_queue)), asyncio.create_task(task("Two", work_queue)), )这种写法依赖顶层的
asyncio.run()来启动事件循环(比如入口函数用asyncio.run(main())),API更简洁,符合Python异步编程的现代范式。旧版显式事件循环风格
需要手动获取事件循环实例,通过loop.run_until_complete()来驱动任务执行:ioloop = asyncio.get_event_loop() tasks = [ioloop.create_task(foo()), ioloop.create_task(bar())] wait_tasks = asyncio.wait(tasks) ioloop.run_until_complete(wait_tasks)这种写法在Python 3.7之前是标准用法,现在除非需要自定义事件循环策略(比如用uvloop替代默认循环),否则不推荐使用。
二、gather与wait的核心差异
1. asyncio.gather:高层级批量等待
- 专注于等待所有任务完成并返回结果,返回的结果列表顺序和输入任务的顺序完全一致。
- 自动处理协程到任务的包装(不过推荐手动用
create_task显式创建任务,更清晰)。 - 默认情况下,只要有一个任务抛出异常,会立即终止并传播异常,其他未完成的任务会被取消;可以通过
return_exceptions=True参数让所有异常被收集到结果列表中,不中断其他任务。 - 适合大多数常规场景:你只需要让一批任务并行执行,最后拿到所有结果,不需要额外的流程控制。
2. asyncio.wait:底层精细化控制
- 返回一个元组
(done, pending),分别包含已完成的任务集合和未完成的任务集合。 - 支持通过
return_when参数控制返回时机:asyncio.ALL_COMPLETED:默认,所有任务完成后返回asyncio.FIRST_COMPLETED:第一个任务完成就立即返回asyncio.FIRST_EXCEPTION:第一个任务抛出异常就立即返回
- 你可以对未完成的
pending任务进行后续操作(比如取消、继续等待),还能结合timeout参数实现超时控制。 - 适合需要精细化管理任务流程的场景:比如分批处理任务、实现超时机制、监听任务完成状态等。
三、总结
你的理解没错:
asyncio.gather(配合现代事件循环写法)适合简化批量任务的等待逻辑,代码简洁,满足大部分日常需求。asyncio.wait(常出现在旧版写法中)适合精细化配置任务的执行策略,提供更灵活的控制能力。
现在优先使用现代async/await风格的写法,只有当需要特殊的任务控制逻辑时,才考虑使用asyncio.wait。
内容的提问来源于stack exchange,提问作者febqij
相关产品推荐
相关产品推荐

