🐍 Python Asyncio 核心架构知识手册一、 核心对象:从“计划”到“结果”概念形象比喻物理本质运行特征Coroutine (协程)一份菜谱async def 函数生成的对象被动性:调用后不运行,必须由 await 或被包装成 Task 才能启动。Future (未来)取餐号牌状态占位符 (Pending -> Finished)结果导向:不包含逻辑。当底层(如网卡)填入数据时,它被标记为完成。Task (任务)正在炒菜的厨师协程的执行包装 (Future 的子类)主动性:创建即“自动挂载”到事件循环队列,具备状态追踪和取消能力。二、 运行逻辑:驱动与让出1. await 的本质挂起:暂时停止当前协程的执行,并在原地打一个“书签”。让出:将 CPU 控制权交还给 事件循环 (Event Loop)。前提:必须配合真正的异步操作(如 asyncio.sleep 或网络 IO)才能真正释放 CPU,否则依然会阻塞。2. Task 的“托管”属性自动调度:asyncio.create_task(coro) 会立即将协程丢进执行队列。并发实现:Task 让你可以在不阻塞主流程的情况下,开启后台长期运行的任务(如心跳检测、日志记录)。三、 典型调用场景场景 A:必须顺序执行代码:data = await get_data()逻辑:我必须拿到数据,才能跑下一行。此时 CPU 会在等待数据时切换去跑别的 Task。场景 B:后台并发执行代码:self._ping_task = asyncio.create_task(ping_loop())逻辑:心跳包应该自顾自地跑,不要管我主程序的进度。场景 C:错误调用(RuntimeWarning)代码:func()(其中 func 是 async 定义的)后果:只产生了一个“协程对象”零件,既没 await 也没 create_task,零件直接掉在地上被垃圾回收。四、 核心面试/回忆点协程和 Task 的区别?协程是逻辑代码(静态),Task 是执行单元(动态)。Task 包装了协程并自动挂载到事件循环中,使其能自主运行。async 方法必须 await 吗?不一定。想等它完事并拿结果,就 await;想让它后台跑,就 create_task。但绝对不能直接调用而不做任何处理。协程和 Future 的区别?协程是干活的过程,Future 是干完活后的那个箱子。Task 将两者结合:它负责跑协程,并把结果塞进 Future。五、 代码片段:TCPServer 中的应用Python# [Task 应用]:后台心跳,自动挂载,不阻塞主程序 self._ping_task = asyncio.create_task(self._ping_loop())
[await 应用]:广播数据,必须确保发送逻辑完成,且在 IO 阻塞时让出 CPU¶
await self._broadcast(msg)
[Future 驱动]:readline 内部通过 Future 监听 Socket¶
当底层网卡有数据时,Future 被填充,await 解开,协程恢复¶
line = await reader.readline() 💡 记忆口诀:协程是计划,Task 是执行;await 是文明礼让,create_task 是后台运行。没 await 也没 Task,协程就是废纸一张。task 可以不await就是在eventloop在任务队列自己跑也可以await