前言
Python asyncio事件循环优势与用法详解。
Operating System: Ubuntu 22.04.4 LTS
参考文档
介绍
Python 的 asyncio
是异步编程的核心库,其核心是事件循环(Event Loop)。通过事件循环,开发者可以高效管理并发任务,尤其适用于 I/O 密集型场景。以下是其优势和用法的详细介绍:
事件循环的优势
高并发性能
在 I/O 密集型任务(如网络请求、文件读写)中,事件循环通过非阻塞 I/O 和协程切换实现高并发,避免了线程/进程切换的开销。例如,单线程可轻松处理成千上万的网络连接。轻量级协程
协程(Coroutine)比线程更轻量,一个线程内可运行数万个协程。协程的切换由事件循环控制,无需操作系统介入,资源消耗极低。清晰的异步代码结构
使用async/await
语法编写的代码类似同步代码,避免了回调地狱(Callback Hell)。例如:async def fetch_data(): data = await some_io_operation() # 非阻塞等待 I/O return data
精准的任务调度
事件循环允许开发者精细控制任务执行顺序、优先级,甚至动态添加/取消任务。
事件循环的用法
基本流程
import asyncio
async def main():
print("Hello")
await asyncio.sleep(1) # 模拟 I/O 操作
print("World")
# 创建事件循环并运行协程
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
运行多个任务
使用 asyncio.gather
或 asyncio.create_task
并发执行任务:
async def task1():
await asyncio.sleep(1)
return "Task1 Done"
async def task2():
await asyncio.sleep(2)
return "Task2 Done"
async def main():
# 同时运行多个任务
results = await asyncio.gather(task1(), task2())
print(results) # ['Task1 Done', 'Task2 Done']
asyncio.run(main())
事件循环 API
获取事件循环:
loop = asyncio.get_event_loop() # 获取当前循环 loop = asyncio.new_event_loop() # 创建新循环
运行直到完成:
loop.run_until_complete(main()) # 运行到 main() 完成
永久运行:
loop.run_forever() # 需手动停止
停止循环:
loop.stop()
与其他线程交互
在非主线程中使用事件循环:
import threading
def start_loop_in_thread(loop):
asyncio.set_event_loop(loop)
loop.run_forever()
new_loop = asyncio.new_event_loop()
t = threading.Thread(target=start_loop_in_thread, args=(new_loop,))
t.start()
# 向子线程中的循环提交任务
async def task():
print("Running in sub-thread")
asyncio.run_coroutine_threadsafe(task(), new_loop)
处理阻塞操作
将阻塞代码委托给线程池执行,避免阻塞事件循环:
async def blocking_io():
await loop.run_in_executor(None, time.sleep, 1) # 将 time.sleep(1) 放到线程池中执行
适用场景
- 高并发网络请求:如 Web 服务器(FastAPI、aiohttp)、爬虫。
- 实时通信:WebSocket、聊天服务器。
- 批量 I/O 操作:文件读写、数据库访问(需异步驱动如
asyncpg
)。
注意事项
- 避免在协程中使用阻塞调用(如
time.sleep()
),需替换为await asyncio.sleep()
。 - 使用异步库:如
aiohttp
(HTTP 请求)、aiomysql
(数据库)。 - CPU 密集型任务需结合多进程(如
ProcessPoolExecutor
)。
通过掌握事件循环的机制和 async/await
语法,可以显著提升程序的并发能力,同时保持代码简洁可维护。建议参考官方文档和实际项目(如 FastAPI)深入学习。
结语
第三百一十篇博文写完,开心!!!!
今天,也是充满希望的一天。