1. Python异步编程与Asyncio核心概念
当我们需要处理大量I/O密集型任务时,传统的同步编程方式会导致程序大部分时间都在等待I/O操作完成。异步编程通过非阻塞的方式让程序在等待I/O时可以处理其他任务,显著提升效率。
Python中的asyncio库提供了完整的异步编程框架,其核心是事件循环(event loop)机制。事件循环负责调度和执行协程(coroutine),当一个协程遇到I/O操作时,会自动挂起并将控制权交还给事件循环,事件循环会立即执行其他就绪的协程。
重要提示:异步编程并不适合CPU密集型任务,因为Python的全局解释器锁(GIL)会限制多线程执行CPU密集型任务。对于这类任务,建议考虑多进程方案。
1.1 协程与普通函数的区别
协程(coroutine)是异步编程的基本单位,使用async def定义。与普通函数不同,调用协程不会立即执行其代码,而是返回一个协程对象。这个对象需要被事件循环调度才会真正执行。
python复制import asyncio
async def my_coroutine():
print("协程开始执行")
await asyncio.sleep(1)
print("协程执行结束")
# 调用协程返回的是协程对象,不会立即执行
coro = my_coroutine()
print(type(coro)) # <class 'coroutine'>
# 需要事件循环来运行协程
asyncio.run(coro)
协程内部可以使用await表达式挂起自身,将控制权交还给事件循环。await后面通常跟着另一个协程或异步I/O操作。
1.2 事件循环的工作原理
事件循环是asyncio的核心,它负责:
- 维护一个任务队列
- 执行就绪的任务
- 当任务遇到I/O操作时挂起它
- I/O完成后将任务重新放入队列
- 重复上述过程直到所有任务完成
python复制import asyncio
async def task1():
print("任务1开始")
await asyncio.sleep(2)
print("任务1结束")
async def task2():
print("任务2开始")
await asyncio.sleep(1)
print("任务2结束")
async def main():
await asyncio.gather(task1(), task2())
asyncio.run(main())
在这个例子中,虽然task1先开始,但由于它的sleep时间更长,task2会先完成。这就是事件循环的调度效果。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Asyncio核心API详解
2.1 创建和运行协程
asyncio提供了几种运行协程的方式:
- asyncio.run() - 运行顶层协程
- 手动管理事件循环
- 使用asyncio.create_task()创建任务
python复制import asyncio
async def fetch_data():
print("开始获取数据")
await asyncio.sleep(2)
print("数据获取完成")
return {"data": 123}
# 方法1: asyncio.run()
result = asyncio.run(fetch_data())
print(result)
# 方法2: 手动管理事件循环
async def main():
task = asyncio.create_task(fetch_data())
await task
print(task.result())
