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.
Django Signals - post_delete()To notify another part of the application after the delete event of an object happens, you can use the post_delete signal.
Django includes a “signal dispatcher” which helps decoupled applications get notified when actions occur elsewhere in the framework. In a nutshell, signals allow certain senders to notify a set of receivers that some action has taken place.
To answer directly: No. It's sync.
There are 3 types of signal. pre_save/post_save: This signal works before/after the method save(). pre_delete/post_delete: This signal works before after delete a model's instance (method delete()) this signal is thrown. pre_init/post_init: This signal is thrown before/after instantiating a model (__init__() method).
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.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With