gc.get_referrers() 用于逆向追踪对象的强引用持有者,助力定位循环引用或意外长生命周期引用;需结合过滤、逐层追溯、主动验证及工具补充,但无法检测弱引用和C层引用。

gc.get_referrers() 本身不直接定位内存泄漏,但它能帮你“逆向追踪”一个对象是谁在持有它——这是排查循环引用或意外长生命周期引用的关键突破口。
先确认目标对象是否真的没被释放
内存泄漏常表现为:本该被回收的对象长期滞留在内存中。先用 gc.get_objects() 或 objgraph 找出疑似“堆积”的对象(比如大量未关闭的连接、重复创建的闭包、缓存字典里的旧实例),再对其中个别典型对象调用 gc.get_referrers(obj),看谁还在引用它。
聚焦可疑引用链,避免信息过载
gc.get_referrers() 返回的是所有直接引用该对象的容器,数量可能很大(尤其对内置类型或常用对象)。建议:
- 先过滤掉 frame 对象(通常是临时栈帧,干扰大):
[r for r in gc.get_referrers(obj) if not isinstance(r, types.FrameType)] - 重点检查字典(
dict)、列表(list)、类实例(your_module.YourClass)、模块(module)等持久性更强的引用源 - 对返回的每个 referrer 再调用一次 gc.get_referrers(referrer),逐层向上追溯,直到找到“根级持有者”(如全局变量、单例、缓存 dict、未清理的回调注册表)
配合 weakref 和 del 主动验证假设
发现某个全局字典 _cache 持有你的对象?试试手动 del _cache[key] 或清空它,再触发 gc.collect(),观察对象是否被回收。如果回收了,基本锁定泄漏源头;如果没回收,说明还有别的引用没被 gc.get_referrers() 捕获(比如 C 扩展、weakref 的 callback、线程局部存储等)。
注意局限:它看不到弱引用和 C 层引用
gc.get_referrers() 只返回 Python 层的强引用。如果你用了 weakref.ref 或 weakref.WeakKeyDictionary,这些不会出现在结果里;C 扩展(如 numpy 数组、某些数据库驱动)持有的引用也看不到。此时需结合 tracemalloc 查分配点,或用 objgraph.show_backrefs()(它内部封装了多次 get_referrers 并可视化)辅助分析。










