Since there is already a Garbage Collector in Python, is deleteLater() necessary in PyQt/PySide?
2 Answers
It depends what you mean by "necessary".
An application could potentially consume a lot of memory if (for example) care is not taken when closing widgets. The QObject-based classes are designed to be (optionally) linked together in a hierarchy. When a top-level object is deleted, Qt will automatically delete all its child objects as well. However, when closing widgets (which are sub-classes of QObject), automatic deletion will only happen if the Qt.WA_DeleteOnClose attribute is set (which, by default, it usually isn't).
To illustrate, try repeatedly opening and closing the dialog in this demo script, and watch how the global list of objects grows:
import sys
from PyQt5 import QtCore, QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.checkbox = QtWidgets.QCheckBox('Delete')
self.button = QtWidgets.QPushButton('Open', self)
self.button.clicked.connect(self.openDialog)
layout = QtWidgets.QHBoxLayout(self)
layout.addWidget(self.checkbox)
layout.addWidget(self.button)
def openDialog(self):
widget = QtWidgets.QDialog(self)
if (self.checkbox.isChecked() and
not widget.testAttribute(QtCore.Qt.WA_DeleteOnClose)):
widget.setAttribute(QtCore.Qt.WA_DeleteOnClose)
for child in self.findChildren(QtWidgets.QDialog):
if child is not widget:
child.deleteLater()
label = QtWidgets.QLabel(widget)
button = QtWidgets.QPushButton('Close', widget)
button.clicked.connect(widget.close)
layout = QtWidgets.QVBoxLayout(widget)
layout.addWidget(label)
layout.addWidget(button)
objects = self.findChildren(QtCore.QObject)
label.setText('Objects = %d' % len(objects))
print(objects)
widget.show()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 300, 100, 50)
window.show()
sys.exit(app.exec_())
With PyQt/PySide, there are two aspects to object ownership: the Python part, and the Qt part. Often, removing the last Python reference to an object won't be enough to fully clean up, because there could still be a reference held on the Qt side.
In general, Qt tends not to implicity delete objects. So if your application creates and removes lots of QObjects (or opens and closes lots of QWidgets), you may need to take steps to delete them explicitly if memory usage is a concern.
UPDATE:
Just to add to the points above on object ownership. Sometimes, it is possible to hold a Python reference to an object, whilst the Qt part gets deleted. When this happens, you will see an error like this:
RuntimeError: underlying C/C++ object has been deleted
Usually, the Qt documentation will give some hints about when this might happen. For instance, QAbstractItemView.setModel gives this warning:
The view does not take ownership of the model unless it is the model's parent object...
This is telling you that you must either keep a Python reference to the object, or pass a suitable parent object to the object's constructor, because Qt will not always automatically reparent it.

- 115,249
- 20
- 229
- 336
-
11)I think there is no difference in PyQt/PySide or Python part , as long as the object is referenced, it will not be cleaned up .Don't you think so ? 2)Besides, WA_DeleteOnClose is suitable for widget that we can close it ,but for QOBject like QNetworkReply and QDialog here closed but isn't be deleted ,deleteLater() is appropriate ,right ? – iMath Nov 25 '13 at 12:48
-
@user1485853. (1) Yes, but see the update to my answer for an important exception. (2) Yes, `WA_DeleteOnClose` is just _one_ common example of when things _might_ not get cleaned up properly. For QOjects, if they have no parent, and no python reference, they will be automatically garbage-collected (eventually) - so no need for deleteLater(). In general, don't worry too much about explicitly deleting objects: beware of "premature optimimization"! Only worry about these issues when you have _real_ evidence that they are causing a problem. – ekhumoro Nov 25 '13 at 18:49
-
1deleteLater() will cause the event loop to delete the object after all pending events have been delivered to it, so it is often safer to use deleteLater() rather than deleting a QObject subclass directly.I found deleteLater() is still useful in PyQt/PySide. – iMath Nov 26 '13 at 11:01
One application of deleteLater
can be cleaning up of yourself, i.e. scheduling a delete of an QObject (for example in threading) to free resources from within the object itself.
Here for example someone is using it in connection with the signal thread.finished. It might be restricted to cases with heavy signalling though.

- 343
- 1
- 7
- 24

- 10,591
- 9
- 64
- 104
-
1Sadly, the example link is now dead. (*Of course. Of course it is.*) – Cecil Curry Jul 18 '18 at 05:13
-
2
-