asyncio核心API

一、asyncio 核心 API —— 常见

1.1 asyncio.run —— 程序的入口

 
# ③ 协程完成后关闭事件循环
 
async def main():
 
    return "hello"
 
result = asyncio.run(main())     # "hello"
 
# ⚠️ 不要在已经有事件循环的地方再调 asyncio.run()——会报错
 

1.2 asyncio.create_task —— 后台并发

常见create_task vs 直接 await 的区别。

 
# ❌ 直接 await:串行
 
async def main():
 
    await download("url1")       # 等 url1 下载完...
 
    await download("url2")       # 才开始下载 url2
 
    # 总时间 = t1 + t2
 
# ✅ create_task:并发
 
async def main():
 
    task1 = asyncio.create_task(download("url1"))   # ① 提交到事件循环——后台执行
 
    task2 = asyncio.create_task(download("url2"))   # ② 提交到事件循环——后台执行
 
    # 两个下载已经在跑了!
 
    result1 = await task1        # ③ 等 task1 完成(可能已经完成了)
 
    result2 = await task2        # ④ 等 task2 完成
 
    # 总时间 ≈ max(t1, t2)
 
 
直接 await(串行):
 
download1: [====运行====]
 
download2:                [====运行====]
 
create_task + await(并发):
 
download1: [====运行====]
 
download2: [====运行====]
 
           ↑ 同时进行——总时间 ≈ 最慢的那个
 

create_task 到底做了什么?

 
create_task(coro)
 

 
① 把协程包装成 Task 对象
 

 
② Task 被注册到当前事件循环
 

 
③ 事件循环在"下次有机会"时开始执行这个 Task
 

 
④ 返回 Task 对象——你可以拿着它 await 或 cancel
 

1.3 asyncio.gather —— 批量并发 + 收集结果

 
# gather:等一批协程全部完成,返回结果列表
 
async def main():
 
    results = await asyncio.gather(
 
        download("url1"),
 
        download("url2"),
 
        download("url3"),
 
    )
 
    # results = [data1, data2, data3]  ← 顺序和传入顺序一致!
 
# 也可以用 * 展开列表
 
urls = ["url1", "url2", "url3"]
 
tasks = [download(url) for url in urls]
 
results = await asyncio.gather(*tasks)
 

gather 的行为细节

 
# ① 默认:一个协程抛异常 → gather 立即抛出,但其他协程不取消
 
async def main():
 
    try:
 
        await asyncio.gather(
 
            download("url1"),         # 正常
 
            download("bad_url"),      # 抛异常!
 
            download("url3"),         # 仍在后台跑
 
        )
 
    except Exception:
 
        pass  # url3 可能还没跑完——但没人等它了
 
# ② return_exceptions=True:异常不抛出,作为结果返回
 
results = await asyncio.gather(
 
    download("url1"),
 
    download("bad_url"),              # 抛异常
 
    return_exceptions=True
 
)
 
# results = [data1, HTTPError("404"), ...]   ← 异常变成了结果项
 

1.4 asyncio.wait —— 更细粒度的控制

 
# 比 gather 更灵活——可以控制"等第一个完成就返回"
 
done, pending = await asyncio.wait(
 
    [download(url) for url in urls],
 
    timeout=5.0,                              # 最多等 5 秒
 
    return_when=asyncio.FIRST_COMPLETED,      # 第一个完成就返回
 
)
 
for task in done:
 
    result = task.result()      # 获取已完成任务的结果
 
for task in pending:
 
    task.cancel()               # 取消还没完成的任务
 
gatherwait
返回值结果列表(按传入顺序)两个集合:(done, pending)
异常处理默认抛异常;可设 return_exceptions异常存在 task 里,不自动抛
超时不支持支持 timeout
完成条件全部完成支持 FIRST_COMPLETED / FIRST_EXCEPTION
使用场景”全部完成,给我所有结果""等第一个完成就行” 或 “加超时”

1.5 asyncio.wait_for —— 单个协程超时

 
# 等一个协程,超时就抛 TimeoutError
 
try:
 
    result = await asyncio.wait_for(
 
        download("slow_url"),
 
        timeout=3.0                      # 3 秒没完成就抛异常
 
    )
 
except asyncio.TimeoutError:
 
    print("太慢了,不等了")
 

1.6 asyncio.as_completed —— 谁先完成先处理谁

 
# 不关心顺序——谁先回来先处理谁
 
async def main():
 
    tasks = [download(url) for url in urls]
 
    for coro in asyncio.as_completed(tasks):      # 返回迭代器——按完成顺序
 
        result = await coro                         # 等最快的那个完成
 
        print(f"完成了一个: {len(result)} 字节")
 

速记卡(面试闪卡)

Q1:一句话讲清「asyncio核心API」到底是什么?

A:asyncio 里 create_task 把协程丢进事件循环后台并发跑,gather 等它们全部完成按序收结果——比串行 await 快到约等于最慢那个。

Q2:create_task:把协程挂上事件循环 —— 怎么理解?

A:像点了两杯奶茶同时做:直接 await 是一杯做完才点下一杯(串行,总时间 t1+t2);create_task 是两杯一起下单一同做(并发,总时间≈max)。create_task 把协程包成 Task 注册到当前循环,返回句柄你再 await 或 cancel。

Q3:gather:批量等全部完成,按序收结果 —— 怎么理解?

A:gather 像发了一叠快递单,等所有包裹到齐才一次性把结果列表给你,且顺序和传入一致。细节:一个协程抛异常,默认 gather 立刻抛但其他协程不取消;设 return_exceptions=True 则把异常当结果项返回,不中断整体。

Q4:wait / wait_for / as_completed:更细的控制 —— 怎么理解?

A:gather 是”全都要”,这仨是”看情况”:wait 返回 (done, pending) 两个集合,支持 FIRST_COMPLETED 和 timeout;wait_for 给单个协程加超时,超了抛 TimeoutError;as_completed 谁先完成先处理谁,不关心顺序。

Q5:何时用哪个 —— 怎么理解?

A:经验:要”全部完成给我所有结果”→gather;要”等第一个完成或加超时”→wait/wait_for;要”边收边处理”→as_completed。共同前提:都基于单事件循环,create_task 是它们能并发的根。

Q6:核心速记主线有哪些?

  • create_task:协程挂上循环后台跑,比串行 await 快

  • gather:等全部完成,结果按传入顺序返回

  • 异常:默认抛出不取消其他;return_exceptions 变结果项

  • wait/wait_for/as_completed:超时、首完成、边到边处理

  • 选型:全收集用 gather,细控用 wait 系

口诀

A:asyncio 并发靠循环,create_task 挂后台;

gather 收齐按序排,wait 超时首完成来;

异常默认抛不 cancel,return_exceptions 装回;

as_completed 谁先到,边收边处理不等待。

相关链接