Search code examples
pythonweak-references

How to reference finalized object in weakref.finalize?


I have a class (that I do not control) that doesn't implement its own cleanup. I thought that this is one of the cases that weakref.finalize is for, but I can't get it working.

def cleanup(obj):
    print('Cleanup obj')
    if not obj.is_closed:
        obj.close()
...

def make_obj():
    obj = SomeClass()

    # this creates an extra ref, so cleanup is never run
    weakref.finalize(obj, cleanup, obj)

    # this always results in ReferenceError; obj is already gone when cleanup is called
    weakref.finalize(obj, cleanup, weakref.proxy(obj))  

Am I doing something wrong? What have I misunderstood?


Solution

  • It is impossible to reference finalized object in weakref.finalize. In "Note" section for weakref.finalize it is stated:

    It is important to ensure that func, args and kwargs do not own any references to obj, either directly or indirectly, since otherwise obj will never be garbage collected. In particular, func should not be a bound method of obj.

    Thus, it is also impossible to orginize cleanup with bound method like weakref.finalize(obj, obj.close). In such case you need to call cleanup function yourself. Another option is to inherit from SomeClass and make proper __del__ method.