[PyQt] signals to python-alive, Qt-dead objects

Giovanni Bajo rasky at develer.com
Fri Apr 23 14:34:40 BST 2010


On Fri, 2010-04-23 at 10:59 +0200, Martin Teichmann wrote:
> Hi List,
> 
> taking the risk of annoying people by asking again,
> (I didn't get a response last time)
> I would like to kindly ask if the following behavior is
> really intended for PyQt4:
> 
> If a QObject is not used anymore, it gets deleted by
> Qt, and eventually garbage collected some time later.
> In the meantime, however, PyQt4 still delivers signals
> to the object, leading to a RuntimeError, since the
> C++ object is already deleted. C++ has the standard
> behaviour that upon deletion of an object, all signals
> automatically get disconnected. This is very useful,
> since I (as a programmer) don't need to care about this
> anymore.
> 
> So, if this intended behaviour, how do I go about it?
> Sure, I could write a try:...except RuntimeError: around
> every method that I use as a slot, but that's some pain.
> 
> If that was directly implemented in PyQt4, it would be
> much simpler: a simple if statement that checks
> if a QObject is still C++-alive before delivering signals would
> do the job. I also cannot see any drawbacks: since the
> receiving object cannot do much anymore anyway,
> given that its object has been deleted, I cannot imagine
> that anyone depends on the current behaviour.
> 
> I re-send the code that shows the problem, I just tested
> it with PyQt 4.7.3 under Python 2.6 and Windows XP.
> Note that the garbage collection at the very end does
> make a difference, which it should never do, since
> it happens at random intervals and is thus not
> reliable (all of which is intended behaviour).
> 
> Greetings
> 
> Martin
> 
> ------------------------ snip ----------------------------
> from PyQt4.QtCore import QObject, SIGNAL, QCoreApplication
> import gc
> 
> # following two lines not important
> from sys import argv
> app = QCoreApplication(argv)
> 
> class A(QObject):
>    def __init__(self, p=None):
>        QObject.__init__(self, p)
> 
>    def g(self):
>        self.emit(SIGNAL("sig"))
> 
>    def k(self):
>        self.emit(SIGNAL("kill"))
> 
>    def f(self):
>        try:
>            print self.children() # only to test if C++ object is still alive
>        except RuntimeError:
>            print "hey, caught runtime error!"

FYI, you can check the C++-dead condition with sip.isdeleted().

And you can destroy the C++ instance from Python (thus forcing an
immediate destruction of the actual object/widget, irrespective of when
the Python wrapper will be garbage-collected) with sip.delete().

-- 
Giovanni Bajo   ::  rasky at develer.com
Develer S.r.l.  ::  http://www.develer.com

My Blog: http://giovanni.bajo.it
Last post: Grey on black: combining greylisting with blacklists



More information about the PyQt mailing list