用__del__观察Python和PyQt中的对象破坏

2022-05-05 00:00:00 python pyqt pyside garbage-collection

问题描述

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

我想在某个时间点删除对象A和B的整个互连结构。我只需调用A.deleteLater(),这是为Qt对象推荐的。在我看来,它工作得很好,删除了A和B,因为它们没有外部引用,只有相互的引用……但问题是,我不太确定它是否真的有效,它是否可靠,它是否会在所有地方都适用,例如,如果有人将B级划分为B级,是否会有任何危险。

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

所以基本上有两个问题:

  1. 这种deleteLater()用法正确可靠吗?和

  2. __del__析构函数中的消息打印是否会影响垃圾回收器?或者在调试期间还可以使用哪些其他方法来观察和确认破坏?


解决方案

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

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

相关文章