Python3中协程 一、核心概念协程是什么协程是一种用户态的轻量级“任务”它允许函数在执行过程中主动挂起暂停和恢复。与操作系统调度的线程不同协程由程序员或程序运行时如 Python 的 asyncio 库显式调度切换开销极小。# 一个最简单的协程示例 import asyncio async def main(): print(hello) await asyncio.sleep(1) # 模拟I/O操作挂起协程 print(world) # 运行协程 asyncio.run(main()) # 输出: hello - (等待1秒) - world核心特性可暂停/可恢复函数执行到 await 处可以让出控制权之后能从暂停点继续执行。单线程协作在单线程内运行多个协程同一时刻只有一个协程执行通过协作式多任务交替执行。高效 I/O 处理在等待 I/O如网络请求、文件读写时主动让出执行权给事件循环去执行其他协程充分利用等待时间。为了更直观地理解协程、线程与进程的区别请看下表特性协程线程进程调度方式用户程序如asyncio操作系统内核操作系统内核切换开销极小函数调用级别中等极大数据共享简单同一进程内需要锁机制竞争条件需要IPC复杂适用场景I/O 密集型高并发网络、爬虫、Web服务I/O 密集型但受GIL限制CPU 密集型、计算密集型利用多核❌单线程内❌受GIL限制Python多线程无法利用多核malaoshi.top✅典型代表asyncio库threading模块multiprocessing模块协程的威力在于用更少的资源处理更多的并发连接。一个协程在等待网络响应时事件循环可以切换执行成百上千个其他协程而无需创建昂贵的线程或进程。二、语法基石async/await 与事件循环现代 Python 协程基于 async/await 语法和 asyncio 标准库。1. async def 与协程对象使用 async def 定义协程函数。调用协程函数不会立即执行函数体而是返回一个协程对象async def demo(): print(开始执行) await asyncio.sleep(1) print(结束执行) # 直接调用得到协程对象不会运行代码 coro_obj demo() print(type(coro_obj)) # class coroutine2. await 关键字await 用于等待一个可等待对象 的完成并将控制权交还给事件循环。可等待对象主要有协程对象由协程函数调用产生。Task对协程的进一步封装用于在事件循环中调度。Future更底层的抽象代表一个异步操作的最终结果。执行规则await 只能在 async def 函数内部使用。执行到 await 时当前协程暂停事件循环调度其他任务等待的对象完成后再恢复当前协程。3. 事件循环调度中心事件循环是每个 asyncio 应用的核心。它像一个永不停歇的“调度员”负责运行异步任务和回调。执行网络 I/O 操作。分发事件如 I/O 完成。其核心工作流程如下图所示运行协程最简单的方式是使用 asyncio.run()它会自动创建事件循环、运行协程并关闭循环。三、串行import asyncio import time async def say_after(delay, msg): await asyncio.sleep(delay) print(msg) async def main(): start time.time() await say_after(1, A) await say_after(1, B) print(f耗时: {time.time() - start:.2f}s) asyncio.run(main())执行顺序A 跑完再跑 B串行等待。四、并发执行让协程飞起来协程的真正威力在于并发执行多个任务。有两种主要方式1.asyncio.gather()- 批量调度最常用gather可以并发运行多个可等待对象并等待它们全部完成后按入参顺序返回结果列表。import asyncio import time async def fetch(name: str, delay: float) - str: print(f{name} 开始) await asyncio.sleep(delay) # 模拟网络延迟 print(f{name} 完成) return f{name} 的结果 async def main(): start time.perf_counter() # 并发执行三个任务总耗时 ≈ 最长的任务 (2秒) results await asyncio.gather( fetch(任务A, 1.0), fetch(任务B, 2.0), fetch(任务C, 1.5) ) elapsed time.perf_counter() - start print(f所有结果: {results}) print(f总耗时: {elapsed:.2f}s) # 约 2.00s asyncio.run(main())2、asyncio.create_task() - 创建任务create_task 会将协程包装成 Task 对象并立即调度其执行。async def main(): # 创建任务任务立即开始调度执行 task1 asyncio.create_task(fetch(任务A, 1.0)) task2 asyncio.create_task(fetch(任务B, 2.0)) print(任务已提交主协程继续执行...) # 等待任务完成 await task1 await task2⚠️注意直接顺序await两个协程是串行执行无法并发 # ❌ 错误示范总耗时 ≈ 1 2 3 秒 async def main(): await fetch(任务A, 1.0) await fetch(任务B, 2.0)