[PyKDE] How to detect if an object has been deleted

dmiller dmiller at tcwcomputers.com
Mon Sep 18 14:26:16 BST 2006


Thanks Giovanni!

~ Daniel


On Sep 18, 2006, at 9:16 AM, Giovanni Bajo wrote:

> Daniel wrote:
>
>> Is there a documented way to detect if the underlying object has been
>> deleted? Here's a short example that works, but it feels a bit dirty:
>>
>> def is_deleted(obj):
>>      try:
>>          obj.name
>>      except RunTimeError, ex:
>>          if str(ex) == "underlying C/C++ object has been deleted":
>>              return True
>>          raise
>>      return False
>>
>> There are obvious problems with this solution:
>>
>> - it depends on the exception message
>> - it depends on an unrelated interface to produce the error (i.e.
>> "name" must be a non-overridden member on the underlying object)
>
> I'd use the following:
>
> def is_deleted(obj):
>    import sip
>    try:
>       sip.unwrapinstance(obj)
>    except RuntimeError:
>       return True
>    return False
>
> For PyQt (QObject), calling a simple function (like name(), or  
> parent()) and
> catching RuntimeError (that is, without caring of the error  
> message) is
> enough. I have succesfully used this method to implement  
> "qtweakref", which
> uses the actual lifetime of the C++ object instead of that of the  
> Python
> wrapper.
>
> qtweakref.py:
> ===============================================================
> from qt import *
> import weakref
>
> class qtref(weakref.ref):
>     __slots__ = "_callback",
>
>     def __new__(typ, o, callback=None):
>         if not isinstance(o, QObject):
>             wr = weakref.ref.__new__(weakref.ref, o, callback)
>             wr.__init__(o, callback)
>             return wr
>         wr = weakref.ref.__new__(typ, o)
>         if callback is not None:
>             wr._callback = lambda: callback(wr)
>             QObject.connect(o, SIGNAL("destroyed()"), wr._callback)
>         return wr
>
>     def __call__(self, *args, **kwargs):
>         o = super(qtref, self).__call__(*args, **kwargs)
>         if o is None:
>             return None
>         try:
>             o.parent()
>         except RuntimeError:
>             return None
>         return o
>
>     def __repr__(self):
>         o = self()
>         if o is not None:
>             return "<qtweakref at %08X; to '%.50s' at %08X>" % (id 
> (self),
> type(o).__name__, id(o))
>         return "<qtweakref at %08X; dead>" % id(self)
> ===============================================================
>
>
>>>> from qt import *
>>>> import qtweakref as weakref
>>>> qApp = QApplication([])
>>>>
>
>>>>
>>>>
>>>> a = QObject(None)
>>>> r = weakref.ref(a)
>>>> r
> <qtweakref at 2E2048A0; to 'QObject' at 2E2014F8>
>>>> a.deleteLater()
>>>> qApp.processEvents()
>>>> r
> <qtweakref at 2E2048A0; dead>
>>>> a
> <qt.QObject object at 0x2E2014F8>
>>>>
>>>>
>>>>
>>>> a = QObject(None)
>>>> def cb(wr):
> ...     print "dead:", wr
> ...
>>>> r = weakref.ref(a, cb)
>>>> a.deleteLater()
>>>> qApp.processEvents()
> dead: <qtweakref at 2E204870; dead>
>
> -- 
> Giovanni Bajo
>




More information about the PyQt mailing list