Trying to learn more about PyQt I wrote a small script that:
- Creates an
QObjecta - Creates an
QObjectbwithaas its parent - Deletes
a
At this point I expect the object to which the name b is point to have been deleted as well. The documentation of Qt (not PyQt!) says:
The parent takes ownership of the object; i.e., it will automaticallydelete its children in its destructor.
But b still points to an existing object.
I also tried an explicit garbage collection without any change.
Trying to access a via b's parent() method fails though, as expected.
Why is the QObject referenced by b not deleted when a, which "owns" b, is deleted?
I have added the print outputs as comments below:
import gcfrom PyQt5.QtCore import QObjectdef tracked_qobjects(): return [id(o) for o in gc.get_objects() if isinstance(o, QObject)]def children(qobject: QObject): return [id(c) for c in qobject.findChildren(QObject)]a = QObject()b = QObject(parent=a)print(f"QObjects tracked by gc: {tracked_qobjects()}")# QObjects tracked by gc: [140325587978704, 140325587978848]print(f"Children of a: {children(a)}")# Children of a: [140325587978848]del aprint(f"QObjects tracked by gc: {tracked_qobjects()}")# QObjects tracked by gc: [140325587978848]gc.collect() # not guaranteed to clean up but should not hurtprint(f"QObjects tracked by gc: {tracked_qobjects()}")# QObjects tracked by gc: [140325587978848]# Since https://doc.qt.io/qt-5/qobject.html#details says:# "The parent takes ownership of the object; i.e., it will automatically delete# its children in its destructor."# I expect that b now points to a non-existent object.# But no, this still works! Maybe because we are in PyQt5 and# not a C++ application?print(id(b))# 140325587978848print(b)# <PyQt5.QtCore.QObject object at 0x7fa018d30a60># The parent is truly gone though and trying to access it from its child raises the "wanted" RuntimeErrorprint(b.parent())# RuntimeError: wrapped C/C++ object of type QObject has been deleted