Python/PyQt QDialog with connect lambda "leaks"
-
@kshegunov
I have never defended Python! I don't have a choice for my Qt work, if I did I'd prefer C++. I just like C# or plain C.deleteLater()
is a possibility, requires code changing. It's not "one dialog" it's "the code [I didn't write] has loads & loads of dialogs, I have absolutely no idea which ones might have "connect-lambda-self"s (or maybe other idioms?) somewhere in them". If IdeleteLater()
after all of them (lots of places), seems I might just as wellQDialog.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
on all of them in initializer. That one worries because presumably then code must not be accessing any members of dialog after it's been closed, and I think some code does want to do that, and that would go wrong, right?Sigh.
-
@JonB said in Python/PyQt QDialog with connect lambda "leaks":
That one worries because presumably then code must not be accessing any members of dialog after it's been closed, and I think some code does want to do that, and that would go wrong, right?
Right. I would prefer the
deleteLater
to the attribute, if it works at all, as you have a clear idea where is the deletion happening - just after you return control to the event loop. -
@kshegunov
Yes, I agree, but that requires me to go through code finding all cases where a dialog is shown (e.g.exec()
) and appending that line. And I still don't really know when it's "safe", because I don't know whether there is a later code path which requires to access the dialog's information after closure.Since I haven't got time to do that, and since it's easy to do because I sub-class all my
QDialog
s via my own class, for now at least I have putQDialog.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
into my derived class's constructor (if you can really call it that in Python, it's the__init__()
method). Callers could then undo that immediately after construction if they want (i.e. it's just the default behaviour), if & when I ever get time to look through. I'll have to run with it and see....None of this actually addresses the fundamental "closure-leakage" situation I describe, and I don't know if that principle could be applying in other cases in code. I knew there was a good reason why I never want to use lambdas in languages (at least Python)! Does C have them? No, never needed them. Does C#? Yes, in later versions, but I already have avoided them deliberately. Does C++ have them? Yes in newer versions, but then in practice C++ programs leak like a sieve anyway, so I don't expect much ;) "KISS".
Thanks for your input.
-
@JonB said in Python/PyQt QDialog with connect lambda "leaks":
Yes, I agree, but that requires me to go through code finding all cases where a dialog is shown (e.g. exec()) and appending that line. And I still don't really know when it's "safe", because I don't know whether there is a later code path which requires to access the dialog's information after closure.
If you ask me, find a better code 'cause this one seems very suspicious ... ;)
practice C++ programs leak like a sieve
Hey! My programs don't leak, and if they ever do it's a little drip, no gushing.
-
If you ask me, find a better code 'cause this one seems very suspicious ... ;)
32K lines of existing code I inherited. Whadda you want me to do about it? ;)
Hey! My programs don't leak, and if they ever do it's a little drip, no gushing.
I do not doubt that you are (pretty) perfect :) However, have a look through the code posts on this forum of users' real-world Qt/C++ code and send me £1 for each time you spot where they have left a leak....!
-
@JonB said in Python/PyQt QDialog with connect lambda "leaks":
32K lines of existing code I inherited. Whadda you want me to do about it? ;)
hopfuly it's at least decently structured and named/commented !?
Because I remember legacy code that was handed to me with things like 3000 lines inside the main() function and stuff.Hey! My programs don't leak, and if they ever do it's a little drip, no gushing.
I do not doubt that you are (pretty) perfect :) However, have a look through the code posts on this forum of users' real-world Qt/C++ code and send me £1 for each time you spot where they have left a leak....!
I have to admit, early on in my days I had a slack stance on that as well. Usually with the mindset, "That class's instance will exist as long as the program is running anyway ".
Until it didn't. Lessen learend, eventually. -
@J.Hilk said in Python/PyQt QDialog with connect lambda "leaks":
Because I remember legacy code that was handed to me with things like 3000 lines inside the main() function and stuff.
The pinnacle of programming for me when I was handed over 60k+ fortran "scientific code" with not one function in it - everything in the main. The globals (i.e. common blocks) were several pages long and everything was "controlled" through infinitely long
if
s. Sufficed to say, no comments were thought to be needed ... So it's never the language, it's the programmer (or lack thereof) that molds the code into life.I have to admit, early on in my days I had a slack stance on that as well. Usually with the mindset, "That class's instance will exist as long as the program is running anyway ".
Leave water dropping on a piece of stone and it'd eat at it eventually ... it wouldn't matter if it's granite, basalt or sandstone, it would eventually succumb to the simple droplet. The moral is: If you're smart and have a self-preservation instinct, don't leak stuff! :)
-
@kshegunov , @J-Hilk
Don't tell anybody I said so, but this perfectly legitimate wikipedia link is actually my favorite language.It doesn't mess about allowing any such thing as comments in the language in any shape or form, and the standard Hello World code is:
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
Programmers are too soft these days....
-
@JonB said in Python/PyQt QDialog with connect lambda "leaks":
Programmers are too soft these days....
I'm just glad, that the EDSAC days are over :-)
-
For the original problem, and https://stackoverflow.com/a/48501804/489865, stating "a connected lambda which references
self
will not be garbage collected", I received the following code function from the PyQt mailing list. I am not going to use it myself unless I have to (I prefer to rewrite code so as not to useself
-referencing lambdas), but I paste it here (untested; and the author states it's for Python 2.7 but should work for Python 3) in case other readers in future might be interested.def connect_lambda(bound_signal, self, func, **kw): # It can be used like this: # Instead of # self.editingFinished.connect(lambda: self.whatever()) # do # connect_lambda(self.editingFinished, self, lambda self: self.whatever()) import weakref r = weakref.ref(self) del self num_args = func.__code__.co_argcount - 1 if num_args < 0: raise TypeError('lambda must take at least one argument') def slot(*args): ctx = r() if ctx is not None: if len(args) != num_args: args = args[:num_args] func(ctx, *args) bound_signal.connect(slot, **kw)