I wanted to use weakref.finalize
to cleanup some background threads when an object goes out of sight, but the finalizer is not run (edit:) when the object is in the module scope.
Note however that the object own no reference to the active threads, I can see no reason for it not to be garbage collected.
An explicit call to del
solves the issue but this is inconvenient.
live demo here: https://ideone.com/kTZsbs
import weakref
import threading
def do(l):
l.acquire()
class A:
def __init__(self):
l = threading.Lock()
l.acquire()
t = threading.Thread(target=do, args=[l])
t.start()
weakref.finalize(self, A._finalize, t, l)
@staticmethod
def _finalize(t, l):
print("finalizing")
l.release()
t.join()
a = A()
# del a does trigger _finalize though
You just need a way to make
a
go out of scope:Output:
As noted by @quamrana, module level objects only get garbage collected when the module is unloaded, so when the interpreter exits in practice.
Unfortunately, active threads also live in the loaded threading module with a refcount > 0, which prevents the current module from being unloaded and therefore the object from being garbage collected...
So the only way to ensure the object is gc is to scope the variable or make sure the threads timeout by themselves.