[PyQt] Inconsistent gc behavior for reference cycles introduced by connections to lambda
Ales Erjavec
ales.erjavec324 at gmail.com
Mon Mar 26 12:57:24 BST 2018
Hi,
There appears to be inconsistency in traversing and GC-ing of some QObject
derived classes.
For instance connecting `QObject.objectNameChanged` signal to a lambda
(capturing
the the QObject instance), lists that lambda in the `gc.get_referents`
(assuming as
implemented by %GCTraverseCode in qobject.sip). Deleting a reference
for the object
and invoking `gc.collect` successfully disposes of the ref cycle.
However for QAbstractItemModel subclasses (QStringListModel,
QStandardListModel, ...)
this is not the case. They do no list the lambda slots in
`gc.get_referents` and leak the
reference cycle.
Example code:
```
import gc
from PyQt5.QtCore import QObject
from PyQt5.QtGui import QStandardItemModel, QTextDocument
obj = QObject()
obj.objectNameChanged.connect(lambda name, obj=obj: obj)
print(gc.get_referents(obj)) # has the lambda in forward reference traversal
del obj
gc.collect()
assert not [obj for obj in gc.get_objects() if isinstance(obj, QObject)]
doc = QTextDocument()
doc.objectNameChanged.connect(lambda name, obj=doc: None)
print(gc.get_referents(doc)) # has the lambda in forward reference traversal
del doc
gc.collect()
assert not [obj for obj in gc.get_objects() if isinstance(obj, QObject)]
model = QStandardItemModel()
model.objectNameChanged.connect(lambda name, obj=model: None)
print(gc.get_referents(model)) # no lambda in forward reference traversal
del model
gc.collect()
assert not [obj for obj in gc.get_objects() if isinstance(obj, QObject)]
```
The last assert fails because QStandardItemModel survived the collection.
Similarly plain QWidget's (and its python derived subclasses) traverse
connected slots,
but its builtin subclasses (QComboBox, QLabel, ...) do not.
There is nothing in the .sip definition files that would stand out as overriding
the default QObject's %GCTraverseCode so I am assuming this is not intended.
Tested on:
* Python: 3.5.4
* PyQt5: 5.9.2, 5.10.1
* OS: macOS 10.11
Regards
Aleš
More information about the PyQt
mailing list