[PySide] QObject.destroyed() is not emitted

Alexey Vihorev vihorev at gmail.com
Thu Nov 29 13:05:14 CET 2012


Ok, let's get less abstract. I got a QTableModel that has to free up some external resources upon its destruction (rollback/close a DB transaction).  In this particular case It's parent is QMdiSubWindow with self.setAttribute(QtCore.Qt.WA_DeleteOnClose), but that is not necessary  - it can be used inside complex widgets, etc.  The code is trivial, but does not work:

class MyModel(QAbstractTableModel):

    def onDestroy(self):
        #Do some housekeeping

    def __init__(self, entity_cls, parent=None, load=True, criteria=None):
        ...	
        self.destroyed.connect(self.onDestroy)
        ...



-----Original Message-----
From: Christian Tismer [mailto:tismer at stackless.com] 
Sent: 29 ноября 2012 г. 6:25
To: Alexey Vihorev
Cc: 'Stephan Deibel'; pyside at qt-project.org
Subject: Re: [PySide] QObject.destroyed() is not emitted

Alexey,

there is not enough context to see your problem.

The behavior in our similar examples is correct:

Noting gets destroyed until we release the references from Python.
As long as you have a reference, no destruction occurs.

By the assignment

   obj = QtCore.Object(),

you create a reference. You do not actively destroy the object by

   del ob

but you just remove one reference. And because nothing else has a reference to it, _then_ the destruction takes place.

The question is about the interaction with other objects.
If everything is correct with PySide (which is certainly still not), then destruction should just work automatically when it's time.

So please give us more of your code.
We cannot see what the real problem is.

cheers - chris

On 29.11.12 04:26, Alexey Vihorev wrote:
> Yes, I tried something like that:
>
> def onDestroy(*args):
>      print('destroyed')
>
> obj = QtCore.QObject()
> obj.destroyed.connect(onDestroy)
>
> obj2 = QtCore.QObject(obj)
> obj2.destroyed.connect(onDestroy)
>
> del(obj)
>
> In this case onDestroy() is called twice, just as it should. But once 
> again
> - omit the last line and nothing Is called. So for it to work explicit 
> destruction must be called at the top of the chain. Which is 
> problematic in my case.
>
> -----Original Message-----
> From: Christian Tismer [mailto:tismer at stackless.com]
> Sent: 29 ноября 2012 г. 0:58
> To: Alexey Vihorev
> Cc: 'Stephan Deibel'; pyside at qt-project.org
> Subject: Re: [PySide] QObject.destroyed() is not emitted
>
> Hi Alexey,
>
> I tried your example and added a parent.
> Right now it looks exactly as it should be:
>
>   >>> def onDestroy(*args):
> ...     print('destroyed')
> ...
>   >>> obj = QtCore.QObject()
>   >>> obj.destroyed.connect(onDestroy) True
>   >>> par = QtCore.QObject()
>   >>> obj.setParent(par)
>   >>> del obj
>   >>> del par
> destroyed
>   >>>
>
> This is PySide on Mac OS X,
>   >>> PySide.__version__
> '1.1.2'
>   >>> QtCore.__version__
> '4.8.3'
>   >>>
>
> Maybe you have some more references to the object?
> For simple refcount checking, you can use sys.getrefcount .
>
>   >>> g=sys.getrefcount
>   >>> g(obj)
> 2
>
> Note that this prints 2 because of the reference from the call. So the 
> object should go away when the one real reference goes away.
> Maybe you have a different problem, involving more objects?
>
> ---------
>
> By the way, PySide seems to be not happy with reference cycles, while 
> pure python is ok with that:
>
>   >>> obj = QtCore.QObject()
>   >>> obj.setParent(obj)
>   >>> g(obj)
> 2
>
> Eeek, that should be 3.
> And if fact.......
>
>   >>> del(obj)
> Segmentation fault: 11
>
> ciao -- Chris
>
>
> On 11/28/12 9:24 PM, Alexey Vihorev wrote:
>> Hi!
>> Well, I understand that if what I need to do is achievable with 
>> explicit deletion,  I should go for it :) The problem is that in my 
>> case the deletion of the object is triggered by deletion of another 
>> object - its parent. But I can't catch the deletion event - neither 
>> of the
> object nor its parent.
>> That's the problem. The whole reason I started looking into that is 
>> that one of my objects needed to free some external resources when
> destroyed.
>> -----Original Message-----
>> From: Stephan Deibel [mailto:sdeibel at wingware.com]
>> Sent: 28 ноября 2012 г. 16:33
>> To: Alexey Vihorev
>> Cc: pyside at qt-project.org
>> Subject: Re: [PySide] QObject.destroyed() is not emitted
>>
>> Alexey Vihorev wrote:
>>> Got problems with the following code:
>>>
>>> from PySide import QtCore
>>>
>>> def onDestroy(*args):
>>>
>>> print('destroyed')
>>>
>>> obj = QtCore.QObject()
>>>
>>> obj.destroyed.connect(onDestroy)
>>>
>>> The onDestroy() method is not called, unless del(obj) is called 
>>> explicitly. In PyQt4 it is called without del(obj). Is that a bug or 
>>> intended behavior? I'm using Qt 4.8.2, PySide 1.1.2 32bit, Windows
>>> 7-64
>>>
>> Since no one responded I'll take a stab at this:
>>
>> I suspect the life cycle of the QObject under PySide is a little 
>> different and the instance will be deleted later during garbage 
>> collection and not immediately when it goes out of scope. I'm 
>> actually not sure why that is happening in PyQt (seems slightly surprising).
>>
>> In general if you want to make sure an instance is deleted at a 
>> particular moment in time, you need to delete it explicitly. By that, 
>> I mean calling some sort of delete method (in PySide I think it's
>> shiboken.delete(obj) and not just "del obj". The latter just deletes 
>> your reference to the instance but doesn't destroy the instance until 
>> all other references are gone and it is garbage collected. Of course 
>> calling
>> shiboken.delete(obj) will be a problem if you still have other 
>> references and try to use them!
>>
>> There is also obj.deleteLater() which marks an object for deletion 
>> but it's not deleted until the event loop is reached again. Depending 
>> on what you're doing this may be a safer way to delete it.
>>
>> At first I thought this might be a refcount bug in PySide. However, 
>> I'm thinking not since "del obj" just deletes your reference to it 
>> and if there were extra references hanging around (either on purpose 
>> or as a result of a refcount bug) then it would not be deleting the 
>> instance at all even after "del obj".
>>
>> I don't understand PySide internals that well so it's possible I'm 
>> missing some subtlety here. I'm going more on my knowledge of Python 
>> in
> general.
>> - Stephan
>>
>> _______________________________________________
>> PySide mailing list
>> PySide at qt-project.org
>> http://lists.qt-project.org/mailman/listinfo/pyside
>


-- 
Christian Tismer             :^)   <mailto:tismer at stackless.com>
Software Consulting          :     Have a break! Take a ride on Python's
Karl-Liebknecht-Str. 121     :    *Starship* http://starship.python.net/
14482 Potsdam                :     PGP key -> http://pgp.uni-mainz.de
phone +49 173 24 18 776  fax +49 (30) 700143-0023
PGP 0x57F3BF04       9064 F4E1 D754 C2FF 1619  305B C09C 5A3B 57F3 BF04
       whom do you want to sponsor today?   http://www.stackless.com/




More information about the PySide mailing list