在 Python 中,async 和 await 是 PEP 492(Python 3.5 引入)定义的关键字,用于支持基于协程(coroutine)的异步编程。它们允许在 I/O 密集型任务中实现非阻塞执行,从而在无需多线程或多进程的情况下提升并发性能。
1. 核心概念
协程(Coroutine):一种可暂停和恢复执行的特殊函数,使用 async def 定义。
事件循环(Event Loop):asyncio 模块提供的核心调度机制,负责协作式运行多个协程。
可等待对象(Awaitable):可与 await 配合使用的对象,通常为协程、Task 或 Future。
2 原理
2.1 挂起点(Suspension Point)
当协程执行到 await expr 时:
expr 必须返回一个可等待对象。
当前协程立即暂停(suspend)。
控制权交还给事件循环。
2.2 事件循环调度与恢复
事件循环持续监控所有可等待对象的状态(如 I/O 完成、定时器到期)。
一旦 await 后面的对象就绪(done() 为真),事件循环将恢复对应协程的执行。
恢复时,从 await 表达式处继续,获取其返回值。
2.3 协程状态机实现
每个协程在底层被编译为一个生成器对象,包含状态机。
await 对应生成器的 yield 点,保存局部变量和执行位置。
事件循环通过 send() / throw() 方法驱动协程前进。
2.4 关键限制与注意事项
只能在 async def 函数内使用 await,否则引发 SyntaxError。
协程不会自动运行,必须通过 asyncio.run()、await 或 create_task() 调度。
阻塞操作会阻碍整个事件循环,应使用异步替代(如 aiohttp 替代 requests)。
2.5. 与线程/进程的对比
总结
async/await 是“单线程、顺序执行、协作挂起”的编程模型,而非抢占式并发。async 定义可暂停的协程函数,await 实现控制权的协作式让渡。其核心在于事件循环驱动的状态机,通过非阻塞等待实现高效并发。合理使用可显著提升 I/O 密集型应用的吞吐量与响应性。
3 例子
import asyncio
import logging
# 配置日志格式:类似 "2025-10-21 12:12:12,902"
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(name)s- %(levelname)s - %(message)s",
)
logger = logging.getLogger(__name__)
async def fetch_data(delay: int) -> str:
logger.info(f"开始获取数据,延迟 {delay} 秒...")
await asyncio.sleep(delay)
logger.info(f"完成获取,耗时 {delay} 秒")
return f"数据(延迟 {delay}s)"
async def main():
task1 = asyncio.create_task(fetch_data(2))
task2 = asyncio.create_task(fetch_data(1))
logger.info("main: 执行到 await task1")
result1 = await task1
logger.info(f"main: 获得 result1 = {result1}")
logger.info("main: 执行到 await task2")
result2 = await task2
logger.info(f"main: 获得 result2 = {result2}")
# 运行
asyncio.run(main())
4 时序图

评论区