[PyQt] QDialog with connect lambda "leaks"

Kyle Altendorf sda at fstab.net
Thu Jul 19 18:28:44 BST 2018


Aside from the situation you are reporting...  This might be relevant to
your code? 

http://doc.qt.io/qt-5/qlineedit.html#setValidator 

Cheers, 

-kyle 

On 2018-07-19 06:30, J Barchan wrote:

> ​​ 
> PyQt 5.7. 
> 
> I have a large body of existing UI code.  I have spent two days commenting in & out bits of code to try to discover why some of its QDialogs "leak" after calling QDialog.exec(). 
> 
> My definition of "leak" here is: after executing from somewhere else 
> 
> dlg = QDialog(self)
> 
> QDialog.exec() 
> 
> the instance of the dialog stays in existence permanently (as long as the caller exists, which for me is till end of program).  That means that every time that code gets executed, yet another new dialog is left around in memory, which adds up over time.  All I do to test is go into the dialog and immediately close it. 
> 
> I discover this by inspecting QtWidgets.QApplication.allWidgets() and reporting all QDialogs which are still in existence.  I see an ever-increasing number of these dialogs, one per each time it's constructed and executed, when & only when the code in the dialog is as follows. 
> 
> I have finally tracked down the problematic line in the dialog's __init__().  Some of them have: 
> 
> from elsewhere import ensureValidDecimal
> self.lineEdit = QLineEdit(self)
> self.lineEdit.editingFinished.connect(lambda: ensureValidDecimal(self)) 
> 
> _The vital bit is: they connect() to a lambda which references SELF._ 
> 
> If the lambda does not need to pass self out as an argument, there will be no leak. 
> 
> If I go define (in this case) in the dialog (I actually sub-class from all my QDialogs so I can add stuff) a dedicated function to avoid the lambda: 
> 
> def selfEnsureValidDecimal(self) 
> ensureValidDecimal(self) 
> 
> self.lineEdit.editingFinished.connect(self.selfEnsureValidDecimal) 
> 
> then there will also be no leak. 
> 
> I can see that at some deep level there must be a reference counting issue here.  In some shape or form, the fact that we have a lambda which passes self to the outside world must mean Python/PyQt wants to keep a reference to the dialog and this must be preventing its destruction. 
> 
> But I don't know what to do about it.  There is a lot of code with a lot of dialogs with all sorts of code attached.  So I need some kind of explanation of what exactly can or cannot be done here, what to look for in code, etc.  Note that I do _not_ wish to use QDialog.setAttribute(QtCore.Qt.WA_DeleteOnClose, True) on all my dialogs (I _believe_ that would solve the leak, but it's not the point).  What must I _not_ do if I do not expect such a self-reference to be left around preventing Python/PyQt from actually freeing up the dialog? 
> -- 
> 
> Kindest, 
> Jonathan 
> _______________________________________________
> PyQt mailing list    PyQt at riverbankcomputing.com
> https://www.riverbankcomputing.com/mailman/listinfo/pyqt
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20180719/7411ec2c/attachment-0001.html>


More information about the PyQt mailing list