async函数内存泄漏的核心原因是协程未被await或未被正确管理,导致任务悬挂、异常静默、资源未释放;关键在“没await”而非“写async”,需确保协程被驱动、任务被跟踪、异常被处理、资源被显式关闭。

async 函数执行中出现内存泄漏,核心原因不是“函数本身泄漏”,而是协程启动后未被正确驱动、异常未被触发、结果未被消费,导致任务长期悬挂(dangling),持续持有上下文和引用。关键不在“写 async”,而在“没 await”或“没处理完”。
漏掉 await 是最直接的泄漏源头
调用 async 函数却未 await,Python 只返回一个协程对象,函数体根本不会执行——既不跑逻辑,也不抛异常,更不释放资源。这个协程对象若无引用、未被调度,就成了“幽灵协程”,占用内存却不干活。
- 错误写法:
fetch_data()→ 返回<coroutine object>,静默存在 - 正确写法:
await fetch_data()→ 协程真正挂起/恢复,异常可被捕获,生命周期可控 - 常见高危点:同步函数里误调异步函数、for 循环中某次分支漏 await、条件判断后忘记 await 分支
Task 创建后未管理,等于放任自流
用 asyncio.create_task() 启动任务,只是把它丢进事件循环;若不保存引用、不 await、不 cancel,它就变成“孤儿任务”。尤其在长周期服务中,这类任务越积越多,CPU 和内存持续上涨。
- 务必把 task 加入集合(如
set或list)统一跟踪 - 退出前主动
task.cancel()+await asyncio.gather(..., return_exceptions=True) - 避免只创建不保存:
asyncio.create_task(worker())单独一行 = 潜在泄漏
异常被静默吞掉,协程就卡在悬挂状态
async 函数里抛了异常,但没人 await 它,异常就一直锁在协程对象里出不来。协程无法正常结束,状态机不退出,局部变量、闭包引用、上下文对象全被钉住,GC 无法回收。
- 检查
task.exception()可安全读取异常(不抛出),适合日志记录 -
await task会原样抛出异常,适合需要中断流程的场景 - 启用 debug 模式:
asyncio.run(main(), debug=True),未 await 的协程会触发RuntimeWarning
资源未显式关闭,泄漏会叠加放大
async 函数常操作连接、文件、流等资源。即使协程结束,若忘了 await writer.wait_closed() 或 async with,底层 socket、fd、缓冲区仍驻留内存。
- 优先使用
async with管理资源(自动__aexit__) - 手动关闭时,务必配对
close()+await wait_closed() - 网络请求、数据库连接、临时文件句柄,每一处都要确认释放路径

















