贝利信息

Python weakref 如何正确使用来避免循环引用内存泄漏

日期:2026-01-24 00:00 / 作者:舞夢輝影
weakref仅在双向引用且需避免父对象因子对象存活而无法回收时使用;单向引用、临时对象或生命周期一致的组合不应使用,否则增加理解成本和空引用风险。

weakref 什么时候该用,什么时候不该用

当对象之间存在双向引用(比如父容器持子对象引用,子对象又通过 parent 属性反向持有父引用),且你明确不希望父对象因子对象存活而无法被回收时,weakref 才是合理选择。它不是通用“防泄漏”工具——对单向引用、临时对象、或生命周期天然一致的组合,强行加 weakref 反而增加理解成本和空引用风险。

weakref.ref 还是 weakref.WeakKeyDictionary

取决于引用关系类型:

常见踩坑:回调函数里直接捕获强引用

注册回调(如信号、事件监听)时,若在 lambda 或闭包中直接引用了 self 或其他长生命周期对象,即使外部用了 weakref,闭包仍会制造隐式强引用链。正确做法是回调内只存弱引用并显式判空:

def make_callback(obj):
    obj_ref = weakref.ref(obj)
    def callback():
        o = obj_ref()
        if o is not None:
            o.handle_event()
    return callback

错误示例(强引用逃逸):

lambda: self.on_event() ← self 被闭包强持有

替代方案比 weakref 更简单的情况

不是所有循环引用都需要 weakref

真正难处理的是那些混入了自定义 __del__、或嵌套了 C API 对象的循环——这时 weakref 不是银弹,得配合 gc 调试工具定位哪一环没断开。