I try to avoid using inlineCallbacks. There are two cases where I will happily use it though: when I write a method that would need more than a few callback functions, and, more importantly, when the logical flow of a method is non-trivial (i.e., it depends on the returned values or errors of several deferreds).
One inconvenience with inlineCallbacks is that you might have some kind of processing you want done no matter how the function returns, or wherever an error occurs. Two solutions here are 1) to put try/except calls around your various yields, and/or to perhaps do something else with various callbacks that might call defer.returnValue, or 2) expect each caller of your method to deal with the result. I don't like the first of those much (depending on the code), and don't like the second at all. So I wrote a decorator specifically for inlineCallbacks decorated functions: from twisted.internet import defer def inlineCallbacksDecorator(callback, errback=defer.passthru): def wrap(f): def wrapper(*args, **kw): d = f(*args, **kw) if isinstance(d, defer.Deferred): return d.addCallbacks(callback, errback, callbackArgs=args, callbackKeywords=kw, errbackArgs=args, errbackKeywords=kw) # We were used to decorate a non-inlineCallbacks function. raise Exception( 'Function %r was decorated with inlineCallbacksDecorator but ' 'did not return a deferred (did you forget to also decorate ' 'with inlineCallbacks?)' % f.__name__) return mergeFunctionMetadata(f, wrapper) return wrap You can use it like this: def _cbok(result, a, b=None): print 'In _cbok: a=%r b=%r' % (a, b) return result def _cberr(failure, *args, **kw): pass # Do something.... and maybe also return the failure. @inlineCallbacksDecorator(_cbok, _cberr) @defer.inlineCallbacks def frog(a, b=None): print 'a = %r, b = %r' % (a, b) result = yield produceDeferred() # yield produceErr() defer.returnValue(a) The nice/interesting thing about this is that the callback and errback functions get called with the deferred result of calling frog (as decorated by inlineCallbacks) *and* the original arguments passed to frog. You can of course ignore the original args if you're not interested in them. You can argue that this doesn't really buy you anything. That's of course true. It's only a decorator that makes it neater to do certain things. Logging, accounting and error processing come immediately to mind. Just keeping code looking simpler/cleaner is enough of a reason for me. After writing this, I realized it deals with what I was clumsily trying to achieve here http://twistedmatrix.com/pipermail/twisted-python/2009-April/019492.html back in April. Terry _______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python