Python 异步操作详解
Python 的异步操作是一种非阻塞式并发编程模型,它通过协程(Coroutines)在单线程内实现任务并发,避免因 I/O 等待导致的资源浪费。核心机制是**事件循环(Event Loop)**在任务间快速切换。
核心组件
-
协程(Coroutine)
- 使用
async def
定义的函数 - 通过
await
暂停执行并移交控制权 - 示例:
async def fetch_data(): print("Start fetching") await asyncio.sleep(2) # 模拟 I/O 等待 print("Done fetching")
- 使用
-
事件循环(Event Loop)
- 调度器:管理所有协程的执行
- 监控 I/O 事件并在资源就绪时恢复协程
- 基础用法:
import asyncio loop = asyncio.get_event_loop() loop.run_until_complete(fetch_data()) # Python 3.7+ 简化写法: asyncio.run(fetch_data())
-
任务(Task)
- 协程的封装,用于并发调度:
async def main(): task1 = asyncio.create_task(fetch_data()) task2 = asyncio.create_task(process_data()) await task1 await task2
- 协程的封装,用于并发调度:
关键技术
-
异步 I/O 操作
- 使用支持异步的库(如
aiohttp
):import aiohttp async def get_url(url): async with aiohttp.ClientSession() as session: async with session.get(url) as response: return await response.text()
- 使用支持异步的库(如
-
并发控制
- 使用
asyncio.gather()
并行运行:async def main(): urls = [url1, url2, url3] tasks = [get_url(url) for url in urls] results = await asyncio.gather(*tasks)
- 使用
-
同步原语
- 线程安全的锁、信号量等:
lock = asyncio.Lock() async def safe_update(): async with lock: # 临界区操作
- 线程安全的锁、信号量等:
实际应用场景
- 高频网络请求
爬虫/API 调用(响应延迟时 CPU 可处理其他任务) - 微服务通信
服务间异步调用(如 gRPC + asyncio) - 实时数据处理
结合消息队列(如 Kafka + aiokafka) - Web 服务
FastAPI/Uvicorn 异步处理 HTTP 请求
同步 vs 异步示例对比
同步阻塞版本:
import time
def get_page(url):
time.sleep(2) # 模拟网络延迟
print(f"Done: {url}")
start = time.time()
for url in ["url1", "url2", "url3"]:
get_page(url)
print(f"Total time: {time.time()-start:.2f}s") # ≈6秒
异步高效版本:
import asyncio
async def get_page(url):
await asyncio.sleep(2)
print(f"Done: {url}")
async def main():
tasks = [asyncio.create_task(get_page(url)) for url in ["url1", "url2", "url3"]]
await asyncio.gather(*tasks)
start = time.time()
asyncio.run(main())
print(f"Total time: {time.time()-start:.2f}s") # ≈2秒
关键注意事项
- 避免混合阻塞调用
如time.sleep()
会冻结整个事件循环 → 改用await asyncio.sleep()
- CPU 密集型任务
异步模型不提升计算性能(需配合多进程) - 调试工具
使用asyncio.debug
模式或第三方库(如trio
) - 异常处理
协程内需捕获异常:try: await risky_operation() except CustomError: handle_error()
总结
Python 的异步操作通过 asyncio
库实现:
- ✅ 优势:高 I/O 并发、低内存消耗
- ⚠️ 局限:不加速计算任务、代码复杂度增加
- 💡 最佳实践:结合 async/await 语法 + 异步生态库(aiohttp, aioredis 等)