gc.collect()有时不释放循环引用对象,因对象被全局变量、类属性、闭包或c扩展长期持有,或含__del__方法时被移入gc.garbage而非自动清理。

为什么 gc.collect() 有时不释放循环引用对象?
Python 的垃圾回收器(GC)默认启用,但只对「不可达的循环引用」起作用。如果对象被全局变量、类属性、闭包或 C 扩展长期持有,哪怕没有外部强引用,GC 也可能无法判定其可回收——尤其是含 __del__ 方法的对象,会直接被 GC 移入 gc.garbage 而非自动清理。
常见现象:反复创建含相互引用的类实例(如父子节点、观察者与被观察者),sys.getsizeof() 看似没涨,但 psutil.Process().memory_info().rss 持续上升,gc.get_count() 中第 2 或第 3 个计数缓慢增长,说明循环引用在积累。
用 gc.get_referrers() 和 gc.get_referents() 定位循环链
这两个函数是诊断循环引用最直接的工具,但需注意它们返回的是「当前可达」的引用关系,不是静态图谱。必须在疑似泄漏发生后、且对象尚未被 GC 处理前调用。
-
gc.get_referents(obj)返回obj直接引用的所有对象(即它的「孩子」) -
gc.get_referrers(obj)返回所有直接引用obj的对象(即它的「父母」) - 若
A in gc.get_referents(B)且B in gc.get_referrers(A),基本确认 A↔B 循环 - 对疑似对象反复追踪几层(例如:A→B→C→A),就能还原出完整闭环
示例:发现某个 Node 实例未被回收,可这样查:
python-docx Skill功能概述python-docx Skill是一项面向实际任务的技能,主要用于本Skill提供使用python-docx生成专业Word文档的标准方法和最佳实践;生成安全服务方案文档;核心要点生成技术架构设计文档;生成任何需要专业排版的Word文档;核心库 : python-docx;使用与执行辅助库 : docx.shared , docx.enum , docx.oxml.ns;标准代码模板;1. 文档初始化;2. 字体设置(必须!它将相关步骤、工具调用和结果整理方式集
import gc
node = Node()
# ... 触发循环引用逻辑
gc.collect() # 先触发一轮,避免干扰
refs = gc.get_referrers(node)
for r in refs:
if hasattr(r, '__dict__') and node in r.__dict__.values():
print(f"被 {type(r).__name__} 的 __dict__ 持有")
手动解引用的关键位置和陷阱
自动 GC 不可靠时,必须在业务逻辑中主动切断引用。重点不是「删对象」,而是「删引用」。
- 在对象生命周期结束前,显式置空反向引用字段,例如
child.parent = None、observer.subject = None - 避免在
__del__中做任何可能触发新引用的操作(如调用其他对象方法、访问模块级变量),否则极易导致对象卡在gc.garbage - 用
weakref替代强引用是更健壮的方案:将反向引用改为weakref.ref(parent),这样 parent 被删时 child 不会阻止其回收 - 切勿依赖
del obj——它只删名字绑定,不销毁对象;真正有效的是让所有引用消失,包括列表中的元素、字典的值、闭包内的自由变量
验证是否真释放:别只看 id() 或 is
对象被回收后,其内存地址可能被新对象复用,所以 id() 相同 ≠ 同一个对象;is 比较在对象销毁后行为未定义。可靠验证方式只有两种:
- 用
weakref.ref(obj)()返回None,说明原对象已不可达 - 在
gc.garbage列表中检查该对象是否出现过(一旦出现,说明 GC 放弃了它,必须手动清理其内部引用再调用gc.garbage.remove(obj)) - 结合
tracemalloc追踪分配源头:tracemalloc.start(); ...; snapshot = tracemalloc.take_snapshot(),过滤出未被释放的类实例的分配堆栈
最易被忽略的一点:C 扩展(如 NumPy 数组、Pandas DataFrame 内部结构)可能持有 Python 对象的隐藏引用,此时即使 Python 层引用全清,内存也不会归还——得查对应库的文档,找类似 .close()、.release() 或上下文管理器支持。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










