[PyQt] Weird behaviour of destroyed() slots

Giovanni Bajo rasky at develer.com
Sun Jul 27 02:39:47 BST 2008


On Sat, 2008-07-26 at 23:31 +0100, Phil Thompson wrote:
> On Sat, 26 Jul 2008 21:07:09 +0200, Giovanni Bajo <rasky at develer.com>
> wrote:
> > On Sat, 2008-07-26 at 17:10 +0100, Phil Thompson wrote:
> >> On Wed, 23 Jul 2008 15:42:18 +0200, Giovanni Bajo <rasky at develer.com>
> >> wrote:
> >> > Hi Phil:
> >> > 
> >> >
> >>
> >
> =============================================================================
> >> > import sip
> >> > from PyQt4.Qt import *
> >> > 
> >> > called = []
> >> > 
> >> > class Core(QObject):
> >> >      def __init__(self, parent=None):
> >> >          QWidget.__init__(self, parent)
> >> >          QObject.connect(self, SIGNAL("destroyed()"), self.callback)
> >> >          QObject.connect(self, SIGNAL("destroyed()"), lambda: 
> >> > self.callback())
> >> >      def callback(self):
> >> >          called.append("done")
> >> > 
> >> > app = QApplication([])
> >> > core = Core(app)
> >> > sip.delete(core)
> >> > 
> >> > assert len(called) == 2, called
> >> >
> >>
> >
> =============================================================================
> >> > Traceback (most recent call last):
> >> >    File "bugpyqt.py", line 18, in <module>
> >> >      assert len(called) == 2, called
> >> > AssertionError: ['done']
> >> > 
> >> > The slot with "lambda" is called, but the other one is not.
> >> 
> >> The reason is that PyQt knows that self is being destroyed and
> >> self.callback may be a wrapped C++ method (although it isn't in this
> > case)
> >> so it won't invoke it.
> > 
> > Why does it refuse to invoke a wrapped C++ method? Even if self is being
> > destroyed (that is: within its C++ destructor) is still valid to invoke
> > methods AFAICT. After all, it's something that's perfectly doable in C++
> > as well. Or not?
> 
> I had second thoughts after my first response. A wrapped C++ method will
> check to see if the C++ instance has been destroyed anyway, so there is no
> need to check it here as well.
> 
> However, a wrapped C++ method still won't work in exactly the same way as a
> C++ application because the "C++ instance has been destroyed" flag has to
> be set before the destroyed() signal has been emitted. But it's ok for pure
> Python methods.

I'll note that it's still *much* better to have a RuntimeError "c++
instance has been destroyed" rather than the current behavior where the
connection is silently ignored even though the connect() call returns
True. So your fix is a progression even for wrapped C++ methods.
-- 
Giovanni Bajo
Develer S.r.l.
http://www.develer.com




More information about the PyQt mailing list