views:

2239

answers:

8

Hi!

Just want to know what's the common way to react on events in python. There are several ways in other languages like callback functions, delegates, listener-structures and so on. Is there a common way? Which default language concepts or additional modules are there and which can you recommend?

A: 

Personally, I've only seen callbacks used. However, I haven't seen that much event driven python code so YMMV.

David Locke
+2  A: 

I can't speak for common approaches, but this page (actual copy is unavailable) has an implementation of the observer pattern that I like.

Here's the Internet Archive link: http://web.archive.org/web/20060612061259/http://www.suttoncourtenay.org.uk/duncan/accu/pythonpatterns.html

Matthew Maravillas
A: 

I have seen listeners and callbacks used. But AFAIK there is no Python way. They should be equally feasible if the application in question is suitable.

muhuk
+2  A: 

Personally I don't see a difference between callbacks, listeners, and delegates.

The observer pattern (a.k.a listeners, a.k.a "multiple callbacks") is easy to implement - just hold a list of observers, and add or remove callables from it. These callables can be functions, bound methods, or classes with the __call__ magic method. All you have to do is define the interface you expect from these - e.g. do they receive any parameters.

class Foo(object):
  def __init__(self):
    self._bar_observers = []

  def add_bar_observer(self, observer):
    self._bar_observers.append(observer)

  def notify_bar(self, param):
    for observer in self._bar_observers:
      observer(param)

def observer(param):
  print "observer(%s)" % param

class Baz(object):
  def observer(self, param):
    print "Baz.observer(%s)" % param

baz = Baz()

foo = Foo()

foo.add_bar_observer(observer) # function
foo.add_bar_observer(baz.observer) # bound method

foo.notify_bar(3)
orip
+1  A: 

It all depends on the level of complexity your application requires. For simple events, callbacks will probably do. For more complex patterns and decoupled levels you should use some kind of a publish-subscribe implementation, such as PyDispatcher or wxPython's pubsub.

See also this discussion.

Eli Bendersky
+1  A: 

Most of the Python libraries I have used implement a callback model for their event notifications, which I think suits the language fairly well. Pygtk does this by deriving all objects from GObject, which implements callback-based signal handling. (Although this is a feature of the underlying C GTK implementation, not something inspired by the language.) However, Pygtkmvc does an interesting job of implementing an observer pattern (and MVC) over the top of Pygtk. It uses a very ornate metaclass based implementation, but I have found that it works fairly well for most cases. The code is reasonably straightforward to follow, as well, if you are interested in seeing one way in which this has been done.

bouvard
A: 

The matplotlib.cbook module contains a class CallbackRegistry that you might want to have a look at. From the documentation:

Handle registering and disconnecting for a set of signals and
callbacks:

   signals = 'eat', 'drink', 'be merry'

   def oneat(x):
       print 'eat', x

   def ondrink(x):
       print 'drink', x

   callbacks = CallbackRegistry(signals)

   ideat = callbacks.connect('eat', oneat)
   iddrink = callbacks.connect('drink', ondrink)

   #tmp = callbacks.connect('drunk', ondrink) # this will raise a ValueError

   callbacks.process('drink', 123)    # will call oneat
   callbacks.process('eat', 456)      # will call ondrink
   callbacks.process('be merry', 456) # nothing will be called
   callbacks.disconnect(ideat)        # disconnect oneat
   callbacks.process('eat', 456)      # nothing will be called

You probably do not want a dependency to the matplotlib package. I suggest you simply copy-paste the class into your own module from the source code.

codeape
A: 

I'm searching for an implementation to register and handle events in Python. My only experience is with Gobject, but have only used it with PyGtk. It is flexible, but might be overly complicated for some users. I have come across of few other interesting candidates as well, but it's not clear how exactly they compare to one another.

Casey