The following example code creates a Sender class (named Alice). Sender keeps track of interested listeners and notifies them accordingly. In more detail, this is achieved by a dictionary containing a function-event mapping, Sender.listeners.
A listener class can be of any type, here I make a bunch of ExampleListener classes, named Bob,Dave & Charlie. All of them have a method, that is that is subscribed to Sender. The only special thing about the subscribed method is that it should contain three parameters: sender, event, message. Sender is the class reference of the Sender class, so a listener would know who sent the message. Event is an identifier, for which I usually use a string. Optionally, a message is the data that is passed to a function.
A nice detail is that if a listener method throws an exception, it is automatically unsubscribed from further events.
''' Created on 26 dec. 2011 Copyright: Jev Kuznetsov License: BSD sender-reciever pattern. ''' import tradingWithPython.lib.logger as logger import types class Sender(object): """ Sender -> dispatches messages to interested callables """ def __init__(self): self.listeners = {} self.logger = logger.getLogger() def register(self,listener,events=None): """ register a listener function Parameters ----------- listener : external listener function events : tuple or list of relevant events (default=None) """ if events is not None and type(events) not in (types.TupleType,types.ListType): events = (events,) self.listeners[listener] = events def dispatch(self,event=None, msg=None): """notify listeners """ for listener,events in self.listeners.items(): if events is None or event is None or event in events: try: listener(self,event,msg) except (Exception,): self.unregister(listener) errmsg = "Exception in message dispatch: Handler '{0}' unregistered for event '{1}' ".format(listener.func_name,event) self.logger.exception(errmsg) def unregister(self,listener): """ unregister listener function """ del self.listeners[listener] #---------------test functions-------------- class ExampleListener(object): def __init__(self,name=None): self.name = name def method(self,sender,event,msg=None): print "[{0}] got event {1} with message {2}".format(self.name,event,msg) if __name__=="__main__": print 'demonstrating event system' alice = Sender() bob = ExampleListener('bob') charlie = ExampleListener('charlie') dave = ExampleListener('dave') # add subscribers to messages from alice alice.register(bob.method,events='event1') # listen to 'event1' alice.register(charlie.method,events ='event2') # listen to 'event2' alice.register(dave.method) # listen to all events # dispatch some events alice.dispatch(event='event1') alice.dispatch(event='event2',msg=[1,2,3]) alice.dispatch(msg='attention to all') print 'Done.'
No comments:
Post a Comment