
On May 25, 2005, at 11:37 PM, theshz wrote:
Hi, from the documentation I could only find examples where the events are related more to Deferred, i.e., a method call that may take sometime. I'm a little confused about the difference between this and the "traditional" kind of event handling. Are they the same with just different terminology? By "traditional", I mean that in part of the code, I generate an event, say a "step 1 finished event", somewhere else there is a handler waiting for this event. The reactor is responsible for dispatching this event to that handler, which hopefull starts step 2. Or even more, like publish- subscribe: multiple handers can register for the same event. In other words, these events are generated internally, not necessarily by such delays like network, file access, or user input. Is this doable in Twisted?
Deferreds are just objects that have a list of (result, error) callback pairs. When the result or error is available, it's passed to the first appropriate callback. The result or error returned by that callback is sent to the next, etc. Its job is to pass that *single* result on to everything in its callback chain either one or zero times, and then it should be garbage collected because its job is done. The way this would works is like this (bare bones example without any error handling, etc.): ### from twisted.internet import defer, reactor def step1(): d = defer.Deferred() # In two seconds, call the callback with the result 42 reactor.callLater(2.0, d.callback, 7) return d def step2(resultOfStep1): d = defer.Deferred() # In two seconds, call the callback with the result of the # argument times 6 reactor.callLater(2.0, d.callback, resultOfStep1 * 6) return d def doAllSteps(): # step1 returns a deferred d = step1() # step 2 takes the result of step1 as an argument # so we can use it as the callback for the deferred, # since the callback always receives the result as the # first argument d = d.addCallback(step2) # the other thing to note is that step2 returns a deferred, which # will automatically be chained, so we can just return it here # as our deferred return d def main(): def printResultAndQuit(result): print "the answer is:", result reactor.stop() d = doAllSteps() d.addCallback(printResultAndQuit) # this should think for about 4 seconds, # print the answer to everything, and then # return. reactor.run() if __name__ == '__main__': main() ### It is an excellent primitive for building a notification system on top of, but it isn't one. As you can see in Twisted's source, there is rarely a need for an event dispatching system, so one doesn't really exist (there is one on the reactor for startup and shutdown events, but that's about it). In almost all cases the "problem" is solved by: (a) having some particular name for a method to be implemented in a subclass (e.g. subclass LineReceiver and implement lineReceived) (b) using a delegate that implements some method with a particular name (e.g. protocols telling their transport to lose connection, or transports notifying their protocol of a lost connection) (c) using deferreds (i.e. twisted.web.server.Request.notifyFinish) The only one that looks like traditional publish-subscribe is really the reactor's system events (twisted.internet.interfaces.IReactorCore) -bob