Python Async/Await 异步编程详解
Python Async/Await 异步编程详解
异步编程是现代 Python 中处理 I/O 密集型任务的核心技术,它通过 协程 和 事件循环 实现高效并发。以下是核心概念和用法的详细说明:
1. 核心概念
- 协程 (Coroutine):使用
async def
定义的异步函数,可通过await
暂停执行。 - 事件循环 (Event Loop):调度协程的执行,处理 I/O 事件。
async/await
关键字:定义协程和挂起点。
2. 基础用法
import asyncio# 定义协程
async def hello():print("Hello")await asyncio.sleep(1) # 非阻塞等待print("World")# 启动事件循环
asyncio.run(hello()) # 输出: Hello → (等待1秒) → World
3. 关键组件详解
a) 事件循环管理
loop = asyncio.get_event_loop()
try:loop.run_until_complete(hello())
finally:loop.close()
b) 并发执行任务
async def task(name, delay):print(f"{name} started")await asyncio.sleep(delay)print(f"{name} finished")async def main():# 同时运行多个任务await asyncio.gather(task("A", 2),task("B", 1),task("C", 3))# 输出顺序: A开始 → B开始 → C开始 → B结束 → A结束 → C结束asyncio.run(main())
c) 任务控制
async def main():task1 = asyncio.create_task(task("Task1", 2))task2 = asyncio.create_task(task("Task2", 1))await task1 # 等待 task1 完成await task2 # 可在此处取消任务 task2.cancel()
4. 异步 I/O 操作示例
a) HTTP 请求 (aiohttp)
import aiohttpasync def fetch(url):async with aiohttp.ClientSession() as session:async with session.get(url) as response:return await response.text()async def main():html = await fetch("https://example.com")print(html[:100]) # 打印前100字符asyncio.run(main())
b) 文件读写 (aiofiles)
import aiofilesasync def write_file():async with aiofiles.open("test.txt", "w") as f:await f.write("Hello Async!")async def read_file():async with aiofiles.open("test.txt", "r") as f:content = await f.read()print(content) # 输出: Hello Async!asyncio.run(write_file())
asyncio.run(read_file())
5. 高级模式
a) 超时控制
async def long_operation():await asyncio.sleep(10)async def main():try:await asyncio.wait_for(long_operation(), timeout=2.0)except asyncio.TimeoutError:print("操作超时!")
b) 同步原语 (锁)
async def worker(lock, name):async with lock: # 获取锁print(f"{name} 进入临界区")await asyncio.sleep(1)print(f"{name} 离开")async def main():lock = asyncio.Lock()await asyncio.gather(worker(lock, "A"), worker(lock, "B"))# 输出: A进入 → A离开 → B进入 → B离开
6. 常见错误与解决方案
-
错误:忘记
await
async def call():# 错误: hello() 没有被等待hello() # 应改为 await hello()
修正:始终对协程使用
await
。 -
错误:在同步代码中调用协程
# 错误: 在非异步环境中直接调用 result = fetch("https://example.com")
修正:在事件循环中运行(如
asyncio.run()
)。 -
错误:阻塞事件循环
async def bad_task():time.sleep(5) # 同步阻塞函数!
修正:使用异步替代(如
await asyncio.sleep(5)
)。
7. 最佳实践
- 避免混合同步/异步代码:确保 I/O 操作全链路异步。
- 使用任务组:Python 3.11+ 推荐
asyncio.TaskGroup
:async with asyncio.TaskGroup() as tg:tg.create_task(task("X", 1))tg.create_task(task("Y", 2)) # 自动等待所有任务完成
- 限制并发量:使用信号量(
asyncio.Semaphore
)控制资源使用。
8. 适用场景
- ✅ 高并发网络请求 (HTTP/数据库)
- ✅ 实时数据处理 (WebSockets)
- ✅ 微服务通信
- ❌ CPU 密集型任务 (需用
multiprocessing
)
通过合理使用 async/await,Python 程序可以轻松处理 数千个并发连接,同时保持代码简洁。掌握事件循环原理和异步 I/O 库(如 aiohttp
、aiomysql
)是构建高性能应用的关键。