[wxPython-users] wx.lib.pubsub and wx.EVT_CLOSE

Josiah Carlson jcarlson at uci.edu
Sun Jun 3 01:07:20 PDT 2007


"Eric Ongerth" <ericongerth at gmail.com> wrote:
> wx.lib.pubsub is making my day... keeping my custom events nice and straight
> so that I only have to use regular wx.EVTs where absolutely necessary.
> 
> However, I notice that I get PyDeadObjectErrors in the following conditions:
> I subscribe a window to some topic, and then somewhere along the way the
> same window is closed by the user when they're finished with it, then at
> some point the trigger event happens and the topic gets broadcast.  Because
> wxwindows don't actually get destroyed when they're closed, only hidden, the
> Python part of the window is still alive to receive the message it
> subscribed to.  But if the action it takes in its message handler references
> any native C++ part that it contained -- such as altering a text control or
> even in some cases referencing variables, a PyDeadObjectError occurs.

Due to the pubsub using weakrefs, if you are using
wx.lib.pubsub.Publisher.subscribe(topic, object.callback_method), then
as long as the rest of your program isn't keeping a reference to the
widget that you destroyed, pubsub should be dropping its reference to
the callback.

As an alternative, as long as you aren't doing dynamic method rebindings
(obj.method = newmethod), you can use a mechanism that can abstracts all
that away and you won't see any more PyDeadObjectErrors anymore...

class method_subscribe:
    def __getattr__(self, methodname):
        def callback_(object, topic):
            #sanity check
            getattr(object, methodname)
            def _callback(message):
                try:
                    meth = getattr(object, methodname)
                except wx.PyDeadObjectError:
                    wx.lib.pubsub.Publisher.unsubscribe(_callback, topic)
                else:
                    meth(message)
            wx.lib.pubsub.Publisher.subscribe(_callback, topic)
        return callback_

subscribe = method_subscribe()

Use it like...

    def __init__(self, ...):
        ...
        subscribe.method(self, topic)
        ...

Generally:
    subscribe.method(self, topic)
is equivalent to:
    Publisher.subscribe(self.method, topic)
with some extra magic thrown in for good measure. :)

 - Josiah





More information about the wxpython-users mailing list