协程(Coroutine):轻量级的并发执行单元
协程是一种用户态线程,可以在执行过程中暂停并在适当时候恢复,是 Python 异步编程的核心。它比线程更轻量(无需内核切换),特别适合 I/O 密集型任务。
核心特性
特性 | 说明 |
---|---|
协作式调度 | 主动让出执行权(非抢占式) |
状态保持 | 暂停时保留局部变量和执行位置 |
高效并发 | 单线程内处理数千个并发任务 |
双向通信 | 可通过 yield 或 await 发送/接收数据 |
协程与生成器的关系
协程是生成器的进化版,两者都使用 yield
,但目的不同:
# 生成器(数据生产者)
def generator():
yield 1
yield 2
# 协程(数据处理者)
def coroutine():
data = yield # 等待接收数据
print(f"Received: {data}")
Python 协程演进史
-
基于生成器的协程(Python 2.5+)
def old_coroutine(): received = yield "ready" print(f"Got: {received}") c = old_coroutine() print(next(c)) # 输出: ready c.send("data") # 输出: Got: data
-
原生协程(Python 3.5+)
async def modern_coroutine(): print("Start") await asyncio.sleep(1) # 非阻塞等待 print("End")
协程、生成器、迭代器的关系
- 迭代器:提供
__next__()
的惰性数据流 - 生成器:用
yield
实现的迭代器 - 协程:扩展生成器,支持双向通信和异步操作
协程使用场景
场景 | 优势 |
---|---|
网络请求(HTTP/DB) | 等待时不阻塞线程 |
高并发服务器 | 单线程处理数千连接 |
数据流管道 | 优雅连接处理步骤 |
状态机实现 | 自然表达复杂状态 |
现代协程(async/await)
Python 3.5+ 原生支持:
import asyncio
async def fetch(url):
# 模拟网络请求
await asyncio.sleep(0.5)
return f"Data from {url}"
async def main():
# 并发执行3个请求
results = await asyncio.gather(
fetch("url1"),
fetch("url2"),
fetch("url3")
)
print(results) # 约0.5秒后输出所有结果
# 运行事件循环
asyncio.run(main())
协程关键组件
-
事件循环(Event Loop)
loop = asyncio.get_event_loop() loop.run_until_complete(task)
-
Future 对象
fut = asyncio.Future() fut.set_result(42) # 设置结果
-
Task 对象
task = asyncio.create_task(coroutine())
协程 vs 线程
特性 | 协程 | 线程 |
---|---|---|
切换开销 | 纳秒级(用户态切换) | 微秒级(内核切换) |
并发数量 | 单线程可处理数万协程 | 通常数百 |
数据共享 | 无需锁(单线程) | 需要同步机制 |
适用场景 | I/O密集型 | CPU密集型 |
调试难度 | 较高(异步逻辑) | 中等 |
典型协程模式
- 生产者-消费者管道
async def producer(queue):
while True:
item = generate_item()
await queue.put(item)
async def consumer(queue):
while True:
item = await queue.get()
process(item)
- 超时控制
async def fetch_with_timeout():
try:
async with asyncio.timeout(1.0): # Python 3.11+
await long_running_task()
except TimeoutError:
print("Timeout!")
协程最佳实践
-
避免阻塞调用
# 错误 ❌ await asyncio.sleep(1) time.sleep(1) # 阻塞整个线程! # 正确 ✅ await asyncio.sleep(1)
-
使用异步库
# 同步库(阻塞) import requests # 异步替代 ✅ import aiohttp
-
限制并发量
sem = asyncio.Semaphore(10) # 最大10并发 async def limited_task(): async with sem: await resource_intensive_task()
总结:Python 执行单元演进
概念 | 特点 | 典型实现 |
---|---|---|
可迭代对象 | 支持多次迭代 | list , dict |
迭代器 | 记录状态的惰性迭代 | iter([1,2,3]) |
生成器 | 动态生成值的迭代器 | (x for x in ...) |
协程 | 可暂停恢复的并发执行单元 | async def |
核心价值:协程在单线程内实现高并发,用同步写法处理异步操作,是现代化 Python 高性能应用的基石。