Python中的协程与异步IO模型
字数 779 2025-11-08 20:56:56
Python中的协程与异步IO模型
协程是Python异步编程的核心概念。让我从基础开始,循序渐进地讲解这个重要的知识点。
什么是协程
协程(Coroutine)是一种比线程更轻量级的并发编程方式。与线程不同,协程的切换由程序自身控制,而不是由操作系统调度。
协程的基本特点
- 协作式多任务:协程主动让出执行权,而不是被强制中断
- 单线程内并发:多个协程可以在单个线程内交替执行
- 高效的上下文切换:协程切换不需要系统调用,开销极小
从生成器到协程
Python的协程是从生成器演化而来的。让我们看一个简单的例子:
def simple_coroutine():
print("协程开始")
x = yield # 暂停点,接收外部传入的值
print(f"接收到: {x}")
y = yield x * 2 # 再次暂停,返回x*2
print(f"再次接收到: {y}")
# 使用协程
coro = simple_coroutine()
next(coro) # 启动协程,执行到第一个yield
result = coro.send(10) # 发送10给协程,继续执行
print(f"返回结果: {result}") # 输出: 返回结果: 20
async/await语法
Python 3.5引入了更清晰的async/await语法:
import asyncio
async def simple_async_coroutine():
print("开始执行")
await asyncio.sleep(1) # 模拟IO操作
print("1秒后")
return "完成"
# 运行异步协程
async def main():
result = await simple_async_coroutine()
print(f"结果: {result}")
# 使用事件循环运行
asyncio.run(main())
事件循环(Event Loop)
事件循环是异步编程的核心引擎,负责调度和执行协程。
事件循环的工作原理
- 维护任务队列:管理待执行的协程任务
- 监控IO事件:通过selector监控文件描述符的读写事件
- 调度执行:当IO就绪时,恢复对应的协程执行
import asyncio
async def task1():
print("任务1开始")
await asyncio.sleep(2)
print("任务1完成")
return 1
async def task2():
print("任务2开始")
await asyncio.sleep(1)
print("任务2完成")
return 2
async def main():
# 并发执行多个任务
results = await asyncio.gather(task1(), task2())
print(f"所有任务完成: {results}")
asyncio.run(main())
异步IO的优势
与传统同步IO对比
同步阻塞方式:
import time
def sync_task(name, delay):
print(f"{name}开始")
time.sleep(delay) # 阻塞整个线程
print(f"{name}完成")
# 顺序执行,总耗时3秒
start = time.time()
sync_task("任务A", 1)
sync_task("任务B", 2)
print(f"总耗时: {time.time() - start}")
异步非阻塞方式:
import asyncio
import time
async def async_task(name, delay):
print(f"{name}开始")
await asyncio.sleep(delay) # 不阻塞线程,让出控制权
print(f"{name}完成")
async def main():
start = time.time()
# 并发执行,总耗时约2秒(最长的任务时间)
await asyncio.gather(
async_task("任务A", 1),
async_task("任务B", 2)
)
print(f"总耗时: {time.time() - start}")
asyncio.run(main())
实际应用示例:异步网络请求
import aiohttp
import asyncio
async def fetch_url(session, url):
try:
async with session.get(url, timeout=10) as response:
content = await response.text()
return f"{url}: 成功, 长度: {len(content)}"
except Exception as e:
return f"{url}: 失败, 错误: {e}"
async def main():
urls = [
"https://httpbin.org/delay/1",
"https://httpbin.org/delay/2",
"https://httpbin.org/delay/1"
]
async with aiohttp.ClientSession() as session:
tasks = [fetch_url(session, url) for url in urls]
results = await asyncio.gather(*tasks)
for result in results:
print(result)
# 运行示例
asyncio.run(main())
关键概念总结
- async def:声明异步函数
- await:等待异步操作完成,让出控制权
- asyncio.run():运行异步程序的主入口
- asyncio.create_task():创建并发任务
- asyncio.gather():并发运行多个协程
- asyncio.sleep():异步延时,不阻塞线程
适用场景
- 高并发IO密集型应用:如网络服务器、爬虫
- 需要大量等待的操作:如数据库查询、文件读写
- 实时数据处理:如WebSocket通信
- 微服务架构:多个服务间的异步调用
协程和异步IO模型让Python能够高效处理大量并发连接,是现代Python高性能编程的重要工具。