为什么 Django 的信号处理默认使用回调的弱引用?

发布于 2024-07-26 10:53:01 字数 445 浏览 1 评论 0原文

Django 文档对此主题是这样说的:

另请注意,Django 存储信号 处理程序作为弱引用 默认,所以如果你的处理程序是本地的 函数,它可能会被垃圾收集。 为了防止这种情况,请在以下情况下传递weak=False: 您调用信号的 connect()。

我无法找到任何理由来解释为什么这是默认的,而且我不明白为什么你会想要一个你显式注册的信号隐式消失。 那么弱引用的用例是什么? 为什么它是默认值?

我意识到在 99% 的情况下,这两种方式可能都不重要,但显然这里有一些我不明白的东西,我想知道是否有任何潜在的“陷阱”有一天可能会咬我。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

茶色山野 2024-08-02 10:53:01

信号处理程序存储为弱引用,以避免它们引用的对象不被垃圾收集(例如在显式删除信号处理程序之后),仅仅因为信号仍在四处飞翔。

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.

奢华的一滴泪 2024-08-02 10:53:01

绑定方法保留对其所属对象的引用(否则,它们无法填充 self,参见 Python 文档)。 考虑以下代码:

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)]

输出:

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

在回调中保留弱引用时需要了解的一件重要的事情是,您不能直接将弱引用绑定方法,因为它们总是动态创建的:

>>> 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>

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文