使用 __del__ 观察 Python 和 PyQt 中的对象销毁

V.K*_*.K. 5 python garbage-collection pyqt pyside

我有一个 PyQt QWidget(对象 A;它只是一个被动容器),其中包含几个子小部件(即有 Qt'ish 父子引用)。A 的子控件从另一个对象(对象 B;不一定是 Qt 对象)引用,该对象为 A 的子控件提供数据,并实际控制 A 的子控件的创建和结构。除了 A 的子对象之外,对象 B 没有其他外部引用。对象 A 引用了对象 B。因此,这是一个纯粹的循环引用教科书示例。

我想在某个时间点删除对象 A 和 B 的整个互连结构。我只需调用A.deleteLater()Qt 对象推荐的方法即可。在我看来,它工作得很好,并删除了 A 和 B,因为它们没有外部引用,只有相互的引用......但问题是,我不太确定它是否真的有效,是否可以依赖它会在任何地方工作,如果有人将 B 子类化会有任何危险。

出于调试目的,我想使用__del__析构函数观察 A 和 B 的正确销毁,该析构函数只会打印类似A was destroyed. 但后来我在文档中了解到,当__del__存在时,垃圾收集器不会收集此类具有循环引用的对象。这是否意味着观察破坏会影响或取消破坏?如果我是对的,这似乎有点像量子力学——观察者的存在会影响实验的结果。

所以基本上有两个问题:

  1. 这种使用是否deleteLater()正确、可靠?和

  2. 析构函数中的消息打印会__del__影响垃圾收集器吗?或者我可以使用哪些其他方法来观察和确认调试过程中的破坏?

小智 1

一种可能的方法是使用对象的弱引用,然后定期检查它是否已被垃圾收集(或强制垃圾收集)。这是一个简单的例子:

>>> import weakref
>>> class Object:
...     pass
... 
>>> o = Object()
>>> r = weakref.ref(o)
>>> r()
<__main__.Object instance at 0x10e8c9e18>
>>> del o
>>> r()
<__main__.Object instance at 0x10e8c9e18>
>>> import gc
>>> gc.collect()
0
>>> r()
>>>
Run Code Online (Sandbox Code Playgroud)