weakref pitfall
Peter Otten
__peter__ at web.de
Sat Oct 20 11:00:46 EDT 2007
Odalrick wrote:
> I'm trying to write a simple game and decided I need an eventmanager.
>
> <code>
> import weakref
> from collections import defaultdict
>
> class _EventManager( object ):
> def __init__( self ):
> self._handled_events =
> defaultdict( weakref.WeakKeyDictionary )
>
> def register( self, handler, event_type, filter=None ):
> self._handled_events[event_type][handler] = filter
>
> def deregister( self, handler, event_type ):
> self._handled_events[event_type].pop( handler, None )
>
> def handle_event( self, event ):
> event_type = event.type
> for handler, filter in
> self._handled_events[event_type].items():
> if filter == None or filter(event):
> handler( event )
>
> eventmanager = _EventManager()
>
> __all__ = [ eventmanager ]
> </code>
>
> Fairly simple, yet there was some strange bug that prevented my game
> from exiting.
>
> I think what happened was that when __init__ ends, self goes out of
> scope, and by extension so does self.handle_quit, Now there are no
> more refeences to self.handle_quit, because weakrefs don't count, and
> the event gets automatically dropped from my eventmanager. I thought
> that wouldn't happen because handle_quit is part of the class and
> instance MainGame.
No, self is yet another reference to the _EventManager instance which
survives the __init__() call because it is also referenced by the
global variable eventmanager.
On the other hand, self.handle_quit creates a new bound-method object every
time which doesn't even live as long as __init__().
> Am I right in my guess? If so, how should I adress this bug? If not,
> what is the bug?
The easiest option, to forget about weakrefs, seems to be the best
here. The other option is to keep a reference to the bound method, e. g.:
class MainGame(object):
def __init__(self, ...):
# put a bound method into the MainGame instance
# you can use a different attribute name if you want
hq = self.handle_quit = self.handle_quit
# register it
eventmanager.register(hq, ...)
Peter
More information about the Python-list
mailing list