Python中的协程(Coroutine)与异步编程
字数 1211 2025-11-23 01:35:35

Python中的协程(Coroutine)与异步编程

描述

协程是Python异步编程的核心概念,它允许函数在执行过程中暂停和恢复,从而高效处理I/O密集型任务。与多线程不同,协程在单线程内通过任务切换实现并发,避免了线程切换的开销和竞争条件问题。Python通过async/await语法和asyncio库原生支持协程。

详细讲解

1. 协程的基本概念

  • 定义:协程是一种特殊的函数,可以在执行过程中暂停(await)并将控制权交还事件循环,待某个操作(如I/O)完成后恢复执行。
  • 优势:相比多线程,协程的上下文切换更轻量,且无需加锁(因为单线程内串行执行协程代码块)。
  • 关键语法
    • async def:声明一个异步函数(协程函数)。
    • await:在协程内部暂停,等待异步操作完成。

2. 创建和运行协程

  • 示例1:定义协程函数

    async def simple_coroutine():
        print("Start coroutine")
        await asyncio.sleep(1)  # 模拟I/O操作,暂停1秒
        print("Resume after 1 second")
    
    • 注意:直接调用simple_coroutine()不会执行其内部代码,而是返回一个协程对象。
  • 示例2:通过事件循环运行协程

    import asyncio
    
    async def main():
        await simple_coroutine()  # 在协程中调用另一个协程
    
    asyncio.run(main())  # 启动事件循环
    
    • asyncio.run()是Python 3.7+推荐的入口点,负责管理事件循环。

3. 并发执行多个协程

  • 问题:若按顺序await多个协程,会串行执行(如先等协程A完成再执行B)。
  • 解决方案:使用asyncio.gather()asyncio.create_task()实现并发。
    async def task(name, delay):
        print(f"Task {name} started")
        await asyncio.sleep(delay)
        print(f"Task {name} finished")
    
    async def main():
        # 方案1:gather同时启动多个协程
        await asyncio.gather(
            task("A", 2),
            task("B", 1)  # B先完成
        )
        # 输出:A开始 -> B开始 -> B结束 -> A结束
    
        # 方案2:create_task创建后台任务
        task_a = asyncio.create_task(task("A", 2))
        task_b = asyncio.create_task(task("B", 1))
        await task_a  # 等待A完成(B可能已先完成)
        await task_b
    

4. 协程的工作原理

  • 事件循环(Event Loop)
    • 核心调度器,维护一个任务队列(协程集合)。
    • 当协程遇到await时,事件循环暂停该协程,转去执行其他可运行的任务。
    • 通过轮询I/O事件(如文件读写、网络请求完成)来唤醒等待中的协程。
  • 状态切换
    • 协程有三种状态:PENDING(等待执行)、RUNNING(运行中)、DONE(完成)。
    • await触发状态从RUNNING转为PENDING,恢复时转为RUNNING

5. 实际应用场景

  • 高性能Web服务器:使用aiohttp库处理大量并发请求。
  • 数据库异步操作:如asyncpg支持PostgreSQL的异步查询。
  • 爬虫并发下载:同时发起多个网络请求而不阻塞主线程。

6. 常见误区与注意事项

  • 避免阻塞操作:协程内不要调用同步I/O函数(如time.sleep()),应使用异步版本(asyncio.sleep())。
  • 错误处理:使用try/except捕获协程内的异常,或通过gather(return_exceptions=True)收集异常。
  • 资源管理:用异步上下文管理器(async with)确保资源(如数据库连接)正确释放。

总结

协程通过async/await将异步代码写得像同步代码一样直观,结合事件循环实现高效并发。掌握协程的创建、调度和错误处理是构建高性能Python应用的关键。

Python中的协程(Coroutine)与异步编程 描述 协程是Python异步编程的核心概念,它允许函数在执行过程中暂停和恢复,从而高效处理I/O密集型任务。与多线程不同,协程在单线程内通过任务切换实现并发,避免了线程切换的开销和竞争条件问题。Python通过 async/await 语法和 asyncio 库原生支持协程。 详细讲解 1. 协程的基本概念 定义 :协程是一种特殊的函数,可以在执行过程中暂停( await )并将控制权交还事件循环,待某个操作(如I/O)完成后恢复执行。 优势 :相比多线程,协程的上下文切换更轻量,且无需加锁(因为单线程内串行执行协程代码块)。 关键语法 : async def :声明一个异步函数(协程函数)。 await :在协程内部暂停,等待异步操作完成。 2. 创建和运行协程 示例1:定义协程函数 注意:直接调用 simple_coroutine() 不会执行其内部代码,而是返回一个协程对象。 示例2:通过事件循环运行协程 asyncio.run() 是Python 3.7+推荐的入口点,负责管理事件循环。 3. 并发执行多个协程 问题 :若按顺序 await 多个协程,会串行执行(如先等协程A完成再执行B)。 解决方案 :使用 asyncio.gather() 或 asyncio.create_task() 实现并发。 4. 协程的工作原理 事件循环(Event Loop) : 核心调度器,维护一个任务队列(协程集合)。 当协程遇到 await 时,事件循环暂停该协程,转去执行其他可运行的任务。 通过轮询I/O事件(如文件读写、网络请求完成)来唤醒等待中的协程。 状态切换 : 协程有三种状态: PENDING (等待执行)、 RUNNING (运行中)、 DONE (完成)。 await 触发状态从 RUNNING 转为 PENDING ,恢复时转为 RUNNING 。 5. 实际应用场景 高性能Web服务器 :使用 aiohttp 库处理大量并发请求。 数据库异步操作 :如 asyncpg 支持PostgreSQL的异步查询。 爬虫并发下载 :同时发起多个网络请求而不阻塞主线程。 6. 常见误区与注意事项 避免阻塞操作 :协程内不要调用同步I/O函数(如 time.sleep() ),应使用异步版本( asyncio.sleep() )。 错误处理 :使用 try/except 捕获协程内的异常,或通过 gather(return_exceptions=True) 收集异常。 资源管理 :用异步上下文管理器( async with )确保资源(如数据库连接)正确释放。 总结 协程通过 async/await 将异步代码写得像同步代码一样直观,结合事件循环实现高效并发。掌握协程的创建、调度和错误处理是构建高性能Python应用的关键。