00310 Python asyncio事件循环优势与用法详解


前言

Python asyncio事件循环优势与用法详解。

Operating System: Ubuntu 22.04.4 LTS

参考文档

介绍

Python 的 asyncio 是异步编程的核心库,其核心是事件循环(Event Loop)。通过事件循环,开发者可以高效管理并发任务,尤其适用于 I/O 密集型场景。以下是其优势和用法的详细介绍:


事件循环的优势

  1. 高并发性能
    在 I/O 密集型任务(如网络请求、文件读写)中,事件循环通过非阻塞 I/O 和协程切换实现高并发,避免了线程/进程切换的开销。例如,单线程可轻松处理成千上万的网络连接。

  2. 轻量级协程
    协程(Coroutine)比线程更轻量,一个线程内可运行数万个协程。协程的切换由事件循环控制,无需操作系统介入,资源消耗极低。

  3. 清晰的异步代码结构
    使用 async/await 语法编写的代码类似同步代码,避免了回调地狱(Callback Hell)。例如:

    async def fetch_data():
        data = await some_io_operation()  # 非阻塞等待 I/O
        return data
  4. 精准的任务调度
    事件循环允许开发者精细控制任务执行顺序、优先级,甚至动态添加/取消任务。


事件循环的用法

基本流程

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.gatherasyncio.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)。

注意事项

  1. 避免在协程中使用阻塞调用(如 time.sleep()),需替换为 await asyncio.sleep()
  2. 使用异步库:如 aiohttp(HTTP 请求)、aiomysql(数据库)。
  3. CPU 密集型任务需结合多进程(如 ProcessPoolExecutor)。

通过掌握事件循环的机制和 async/await 语法,可以显著提升程序的并发能力,同时保持代码简洁可维护。建议参考官方文档和实际项目(如 FastAPI)深入学习。

结语

第三百一十篇博文写完,开心!!!!

今天,也是充满希望的一天。


文章作者: LuYF-Lemon-love
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 LuYF-Lemon-love !
  目录