Question

The Django docs say this on the subject:

Note also that Django stores signal handlers as weak references by default, so if your handler is a local function, it may be garbage collected. To prevent this, pass weak=False when you call the signal’s connect().

I haven't been able to find any justification for why this is the default, and I don't understand why you would ever want a signal that you explicitly registered to implicitly disappear. So what is the use-case for weak references here? And why is it the default?

I realize it probably doesn't matter either way in 99% of cases, but clearly there's something I don't understand here, and I want to know if there's any "gotchas" lurking that might bite me someday.

Was it helpful?

Solution

Signals handlers are stored as weak references to avoid the object they reference from not being garbage collected (for example after explicit deletion of the signal handler), just because a signal is still flying around.

OTHER TIPS

Bound methods keep a reference to the object they belong to (otherwise, they cannot fill self, cf. the Python documentation). Consider the following code:

import gc
class SomeLargeObject(object):
    def on_foo(self): pass

slo = SomeLargeObject()
callbacks = [slo.on_foo]

print [o for o in gc.get_objects() if isinstance(o, SomeLargeObject)]
del slo
print [o for o in gc.get_objects() if isinstance(o, SomeLargeObject)]
callbacks = []
print [o for o in gc.get_objects() if isinstance(o, SomeLargeObject)]

The output:

[<__main__.SomeLargeObject object at 0x15001d0>]
[<__main__.SomeLargeObject object at 0x15001d0>]
[]

One important thing to know when keeping weakrefs on callbacks is that you cannot weakref bound methods directly, because they are always created on the fly:

>>> class SomeLargeObject(object):
...  def on_foo(self): pass
>>> import weakref
>>> def report(o):
...  print "about to collect"
>>> slo = SomeLargeObject()
>>> #second argument: function that is called when weakref'ed object is finalized
>>> weakref.proxy(slo.on_foo, report)
about to collect
<weakproxy at 0x7f9abd3be208 to NoneType at 0x72ecc0>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top