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

4
我有一个PyQt的QWidget(对象A;它只是一个被动容器),其中包含几个子部件(即有Qt样式的父子引用)。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__析构函数中的消息打印是否会影响垃圾回收器?或者我可以使用什么其他方式来观察和确认调试期间的销毁?

基本上,在Python中,“__del__”并不像你可能认为的那样(是C++中“~Destructor()”的类比)。请参见此处此处。简而言之,除非你显式地调用它,否则不能依赖于“__del__”实际被调用。 - aruisdante
但是后来我在文档中了解到,当存在__del__方法时,带有循环引用的对象不会被垃圾回收器收集。但是这对于Python3.4而言已经不再适用,因为实施了PEP442 - mata
可以连接到 someObject.destroyed 信号来查看销毁是否发生。 - mlvljr
1个回答

0

一种可能的方法是使用弱引用来引用对象,然后定期检查它是否已被垃圾回收(或强制进行垃圾回收)。以下是一个简单的示例:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接