gpt4 book ai didi

python - 如何在不保留对连接器的引用的情况下连接到 python 中的 GObject 信号?

转载 作者:太空狗 更新时间:2023-10-30 02:00:47 25 4
gpt4 key购买 nike

问题基本上是这样的,在 python 的 gobject 和 gtk 绑定(bind)中。假设我们有一个在构造时绑定(bind)到信号的类:

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+ 的措辞:

如何使用 weakref 语义为不透明对象提供回调方法?如果连接对象超出范围,则应将其删除并且回调应作为空操作; connectee 不应持有对连接器的引用。

澄清一下:我明确希望避免调用“析构函数/终结器”方法

最佳答案

标准的方式是断开信号。然而,这需要在您的类中有一个类似析构函数的方法,由维护您的对象的代码显式调用。这是必要的,否则您将获得循环依赖。

class ClipboardMonitor(object):
[...]

def __init__(self):
self.clip = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD)
self.signal_id = self.clip.connect("owner-change", self._clipboard_changed)

def close(self):
self.clip.disconnect(self.signal_id)

正如您所指出的,如果您想避免显式破坏,则需要弱引用。我会写一个弱回调工厂,比如:

import weakref

class CallbackWrapper(object):
def __init__(self, sender, callback):
self.weak_obj = weakref.ref(callback.im_self)
self.weak_fun = weakref.ref(callback.im_func)
self.sender = sender
self.handle = None

def __call__(self, *things):
obj = self.weak_obj()
fun = self.weak_fun()
if obj is not None and fun is not None:
return fun(obj, *things)
elif self.handle is not None:
self.sender.disconnect(self.handle)
self.handle = None
self.sender = None

def weak_connect(sender, signal, callback):
wrapper = CallbackWrapper(sender, callback)
wrapper.handle = sender.connect(signal, wrapper)
return wrapper

(这是一个概念验证代码,对我有用——您可能应该根据自己的需要调整这篇文章)。几点注意事项:

  • 我分别存储回调对象和函数。您不能简单地对绑定(bind)方法进行弱引用,因为绑定(bind)方法是非常临时的对象。实际上 weakref.ref(obj.method) 会在创建 weakref 后立即销毁绑定(bind)的方法对象。我没有检查是否也需要存储函数的弱引用...我想如果您的代码是静态的,您可能可以避免这种情况。
  • 当对象包装器注意到弱引用不复存在时,它会将自己从信号发送器中移除。这对于破坏 CallbackWrapper 和信号发送者对象之间的循环依赖也是必要的。

关于python - 如何在不保留对连接器的引用的情况下连接到 python 中的 GObject 信号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1364923/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com