如何在 python 中连接到 GObject 信号,而不保留对连接器的引用?
问题基本上是这样的,在 python 的 gobject 和 gtk 绑定中。假设我们有一个在构造时绑定到信号的类:
class ClipboardMonitor (object):
def __init__(self):
clip = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD)
clip.connect("owner-change", self._clipboard_changed)
现在的问题是,没有 ClipboardMonitor 实例会消亡。 gtk 剪贴板是一个应用程序范围的对象,连接到它会保留对该对象的引用,因为我们使用回调 self._clipboard_changed。
我正在讨论如何使用弱引用(weakref 模块)来解决这个问题,但我还没有拿出一个计划。任何人都知道如何将回调传递给信号注册,并使其表现得像弱引用(如果在 ClipboardMonitor 实例超出范围时调用信号回调,则它应该是无操作)。
添加: 独立于 GObject 或 GTK+ 的表述:
如何使用弱引用语义为不透明对象提供回调方法?如果连接对象超出范围,则应将其删除,并且回调应充当无操作;连接者不应持有对连接器的引用。
澄清一下:我明确希望避免调用“析构函数/终结器”方法
The problem is basically this, in python's gobject and gtk bindings. Assume we have a class that binds to a signal when constructed:
class ClipboardMonitor (object):
def __init__(self):
clip = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD)
clip.connect("owner-change", self._clipboard_changed)
The problem is now that, no instance of ClipboardMonitor will ever die. The gtk clipboard is an application-wide object, and connecting to it keeps a reference to the object, since we use the callback self._clipboard_changed
.
I'm debating how to work around this using weak references (weakref module), but I have yet to come up with a plan. Anyone have an idea how to pass a callback to the signal registration, and have it behave like a weak reference (if the signal callback is called when the ClipboardMonitor instance is out of scope, it should be a no-op).
Addition: Phrased independently of GObject or GTK+:
How do you provide a callback method to an opaque object, with weakref semantics? If the connecting object goes out of scope, it should be deleted and the callback should act as a no-op; the connectee should not hold a reference to the connector.
To clarify: I explicitly want to avoid having to call a "destructor/finalizer" method
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
标准的方法是断开信号。然而,这需要在您的类中具有类似析构函数的方法,由维护对象的代码显式调用。这是必要的,因为否则你会得到循环依赖。
正如您所指出的,如果您想避免显式破坏,则需要弱引用。我会编写一个弱回调工厂,例如:(
这是概念验证代码,对我有用 - 您可能应该根据您的需要调整这一部分)。几点说明:
weakref.ref(obj.method)
会在创建weakref后立即销毁绑定的方法对象。我也没有检查是否需要存储函数的弱引用...我想如果你的代码是静态的,你可能可以避免这种情况。The standard way is to disconnect the signal. This however needs to have a destructor-like method in your class, called explicitly by code which maintains your object. This is necessary, because otherwise you'll get circular dependency.
As you pointed out, you need weakrefs if you want to avoid explicite destroying. I would write a weak callback factory, like:
(this is a proof of concept code, works for me -- you should probably adapt this piece to your needs). Few notes:
weakref.ref(obj.method)
will destroy the bound method object instantly after creating a weakref. I didn't check whether it is needed to store a weakref to the function too... I guess if your code is static, you probably can avoid that.(这个答案跟踪我的进度)
第二个版本也将断开连接;我有一个用于 gobjects 的便利函数,但实际上我需要此类来处理更一般的情况 - 无论是 D-Bus 信号回调还是 GObject 回调。
无论如何,我们可以将
WeakCallback
实现风格称为什么?它是对弱回调的非常干净的封装,但不知不觉地附加了 gobject/dbus 专业化。胜过为这两种情况编写两个子类。(This answer tracks my progress)
This second version will disconnect as well; I have a convenience function for gobjects, but I actually need this class for a more general case -- both for D-Bus signal callbacks and GObject callbacks.
Anyway, what can one call the
WeakCallback
implementation style? It is a very clean encapsulation of the weak callback, but with the gobject/dbus specialization unnoticeably tacked on. Beats writing two subclasses for those two cases.还没有真正尝试过,但是:
not actually tried it yet, but: