python内存泄漏排查核心是定位“本该被回收但一直存活的对象”,需结合tracemalloc查分配源头、gc/objgraph分析循环引用与滞留对象、psutil监控rss趋势,并对照全局容器未清理、闭包持大对象等常见模式自查。

Python内存泄漏排查核心是定位“本该被回收但一直存活的对象”。关键不在于总内存增长,而在于对象数量异常累积或引用链未断开。
用tracemalloc快速定位内存分配源头
这是Python 3.4+内置工具,轻量且精准,适合开发阶段快速定位哪行代码反复申请内存:
- 启动时启用:
import tracemalloc; tracemalloc.start() - 运行可疑逻辑后,获取快照:
snapshot = tracemalloc.take_snapshot() - 按分配大小排序前10行:
top_stats = snapshot.statistics('lineno'); for stat in top_stats[:10]: print(stat) - 重点关注
list.append、dict.__setitem__、字符串拼接(+=)、读大文件未关闭等高频分配点
用gc和objgraph分析循环引用与对象滞留
Python的引用计数无法清理循环引用,需依赖垃圾回收器(gc)。objgraph能可视化对象关系,直击泄漏根因:
- 检查是否启用了gc:
import gc; gc.isenabled()(生产环境勿禁用) - 统计某类对象数量变化:
objgraph.count('YourClassName'),运行前后对比是否只增不减 - 找出增长最多的对象类型:
objgraph.show_most_common_types(limit=20) - 追踪某个泄漏实例的引用链:
objgraph.show_backrefs([leaked_obj], max_depth=5, filename='backref.png'),图中箭头指向即“谁持有它”,常暴露全局列表、缓存、回调注册表等未清理引用
用psutil监控进程级内存趋势
辅助判断是否存在持续增长,排除误报(如临时缓存、JIT预热):
立即学习“Python免费学习笔记(深入)”;
- 定期采样RSS内存:
import psutil; p = psutil.Process(); p.memory_info().rss / 1024 / 1024(单位MB) - 结合业务周期观察:比如每处理100个请求后内存是否回落;若单调上升,再深入对象层分析
- 注意区分:RSS增长 ≠ Python内存泄漏(可能是mmap、C扩展、共享库占用)
常见泄漏模式与自查清单
不必每次从零分析,先核对高频问题:
-
全局容器未清理:日志列表、统计字典、事件监听器集合,在长生命周期模块中持续
.append/[key] = value却无清除逻辑 - 闭包/装饰器持有了大对象:函数内定义的闭包意外捕获了大数据结构(如DataFrame、大字典),且该函数被长期引用(如注册为回调)
-
弱引用误用:
weakref.WeakKeyDictionary键被意外强引用,导致值无法释放;或weakref.ref回调未执行清理 -
第三方库副作用:某些库(如旧版requests、SQLAlchemy session、matplotlib)内部维护连接池或缓存,默认不自动释放,需显式调用
.close()或session.remove()










