[PyQt] signals to python-alive, Qt-dead objects
Martin Teichmann
martin.teichmann at mbi-berlin.de
Fri Apr 23 09:59:02 BST 2010
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!"
def kill(self):
self.setParent(None)
a = A()
b = A(a)
c = A(b)
b.connect(a, SIGNAL("sig"), c.f)
b.connect(a, SIGNAL("kill"), b.kill)
a.g() # deliver signal to c, all fine
c.v = c # create cycle to prevent immediate collection
b = None
c = None
a.k() # now c ceases existence in the C++ world
print "here"
a.g() # signal is still delivered
print "now collect"
gc.collect()
a.g() # signal no more delivered, python object has died
---------------------------------------- snip -----------------------------
More information about the PyQt
mailing list