Python async/await 异步编程
理解协程、事件循环和 async/await 语法,学会编写非阻塞的并发代码。 · 难度:入门 · +15XP
异步编程基础
Python 的 async/await 语法(PEP 492,Python 3.5+)让你可以编写并发代码,而无需使用线程或进程。它特别适合 I/O 密集型任务(如网络请求、文件读写、数据库查询),在这些场景下可以大幅提升效率。
核心概念
- 协程(Coroutine):用
async def定义的函数,调用后返回一个协程对象 - 可等待对象(Awaitable):协程、Task 或 Future,可以用
await等待 - 事件循环(Event Loop):调度和执行协程的运行时环境
基本语法
import asyncio
async def say_hello():
print("你好")
await asyncio.sleep(1) # 模拟异步等待
print("世界")
# 运行协程
asyncio.run(say_hello())
同时运行多个协程
import asyncio
async def fetch_data(url: str, delay: int):
print(f"开始请求 {url}")
await asyncio.sleep(delay) # 模拟网络延迟
print(f"完成请求 {url}")
return f"{url} 的数据"
async def main():
# 并发执行多个任务
results = await asyncio.gather(
fetch_data("https://api1.com", 2),
fetch_data("https://api2.com", 1),
fetch_data("https://api3.com", 3),
)
print("所有结果:", results)
asyncio.run(main())
同步 vs 异步对比
| 场景 | 同步代码 | 异步代码 | 耗时 |
|---|---|---|---|
| 3个网络请求(各1秒) | 顺序执行 | 并发执行 | 同步 ~3s,异步 ~1s |
| CPU 密集计算 | 直接计算 | 需要结合多进程 | 异步无优势 |
常见陷阱
- 不要在协程中使用
time.sleep(),必须用asyncio.sleep() - 在 Jupyter Notebook 中,使用
await前需要先运行import nest_asyncio; nest_asyncio.apply() - 协程不会自动并发,需要显式使用
asyncio.gather()或create_task()
练习提示
在下方代码中,补全 main 函数,使用 asyncio.gather 同时运行两个 download_file 协程,一个延迟2秒,一个延迟3秒。观察总耗时是否接近3秒(而不是5秒)。