人人都会AI编程

async/await 语法、异步编程范式

更新时间:2026-07-12

Python 从 3.5 版本开始引入 asyncawait 关键字,标志着原生协程和异步编程成为语言的一等公民。理解这两个关键字,是进入 Python 异步世界的钥匙。

异步编程解决了什么问题?

在传统的同步 IO 中,当一个任务需要等待网络响应或磁盘读取时,整个线程会被阻塞,什么也做不了。异步编程的核心思想是:在等待 IO 的时间里,不闲着,主动交出控制权去执行其他任务。这样,一个线程就能同时处理成百上千个 IO 密集型任务,极大提高吞吐量。

async def:定义一个协程函数

async def 定义的函数不再是普通函数,而是协程函数。调用它不会立即执行内部的代码,而是返回一个协程对象,需要被事件循环调度才能运行。

# 定义一个协程函数
async def fetch_data():
    print("开始请求数据...")
    await asyncio.sleep(2)   # 模拟网络 IO 等待
    print("数据请求完成")
    return {"status": "ok"}

直接调用 fetch_data() 只会得到一个协程对象,不会打印任何内容。

await:等待一个可等待对象

await 关键字用于挂起当前协程,等待另一个协程(或可等待对象)执行完毕,得到结果后再继续往下走。在挂起期间,事件循环可以转而执行其他任务。

async def main():
    result = await fetch_data()   # 等待 fetch_data 完成,拿到返回值
    print(result)

可等待对象只有三种:协程、asyncio.Taskasyncio.Future。你不能 await 一个普通函数或阻塞操作(如 time.sleep),必须使用异步库提供的对应版本(如 asyncio.sleep)。

事件循环:调度者

要想真正运行协程,必须有一个事件循环。事件循环会不停地检查哪些协程可以继续执行,切换调度。在高级 API 中,asyncio.run() 会自动创建并管理事件循环。

import asyncio

asyncio.run(main())  # 这就是启动整个异步程序的入口

并发执行多个任务:asyncio.gather 与 asyncio.create_task

如果只是顺序地 await 一个接一个的协程,那和同步代码没有区别。真正的并发来自同时启动多个任务

async def task1():
    await asyncio.sleep(1)
    return "任务1完成"

async def task2():
    await asyncio.sleep(2)
    return "任务2完成"

async def main():
    # 并发执行 task1 和 task2
    results = await asyncio.gather(task1(), task2())
    print(results)  # ['任务1完成', '任务2完成']

asyncio.gather 会并发运行多个协程,直到全部完成。另一种方式是 asyncio.create_task,它将协程封装成 Task 并立即提交给事件循环调度。

异步编程范式:协作式多任务

异步编程是一种协作式而非抢占式的多任务模型。一个协程必须主动通过 await 交出控制权,别的协程才有机会运行。这带来了几个关键特性:

  • 非阻塞:所有可能导致阻塞的 IO 操作都必须使用异步版本,否则会卡住整个事件循环。
  • 单线程:默认情况下,asyncio 在单个线程里工作,因此没有多线程常见的竞态、锁等复杂问题。
  • 适合 IO 密集型:对于大量 IO 等待的任务(如爬虫、Web API、数据库查询),异步性能远超多线程。
  • 不适合 CPU 密集型:如果一个协程里包含大量计算,它不主动交出控制权,其他任务就会“饿死”。CPU 密集型任务应交给多进程或线程池。

实际开发中的注意事项

  • 切换要彻底:整个调用链都必须使用 async/await,不能中途混入同步阻塞调用。例如,用 requests 库会卡死事件循环,必须改用 aiohttp 等异步库。
  • 传统同步函数怎么调用asyncio.to_thread(Python 3.9+)可以把同步函数放入线程池执行,避免阻塞事件循环。
  • 调试与测试pytest-asyncio 可以让测试函数也变成协程,方便编写异步测试用例。

异步编程上手稍有门槛,但一旦理解“事件循环 + 协程挂起”的模型,就能写出高性能、低资源的并发程序。它已经成为 FastAPI、异步爬虫、实时通信等场景的标准实践。