[Twisted-Python] inlineCallbacksDecorator

Terry Jones terry at jon.es
Mon Jun 8 16:10:49 EDT 2009

>>>>> "Drew" == Drew Smathers <drew.smathers at gmail.com> writes:
Drew> On Sat, Jun 6, 2009 at 9:41 PM, Terry Jones<terry at jon.es> wrote:
>> 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.

Drew> How does inlineCallbacks preclude you from adding "processing you
Drew> want done no matter how the function returns" or currying callbacks?
Drew> From my understanding of the problem, this is already solved by
Drew> attaching callbacks/errbacks in the regular way:

Drew> @inlineCallbacks
Drew> def foo(a, b, c):
Drew> ...
Drew> foo(a, b, c).addBoth(cb, a, b, c)

Right, that's what I meant by the (2) in my paragraph. The reason that's
not always what you want is that there may be things foo needs to get done
before it returns, things that are best or can only be computed inside
foo. In that case you don't really want to make all your callers have to
add a callback to add functionality/logic that belongs inside foo.

Under normal circumstances you'd have code like this:

  def foo():
    d = someOtherFunc()
    return d


  def foo():
    d = defer.Callback()
    # Set up some stuff that will fire d
    return d

so the deferred that comes back from foo is under control of foo and if
there's any logical last steps to be done to it, foo can easily add them.

But with inlineCallbacks, foo never has its hands on the deferred that will
be returned.  Yes, you could do:

  def foo():
      # All sorts of stuff, yielding deferreds
    except ...:
      # yield somethingElse or raise something

But that's not so attractive, and it only deals with errbacks. To deal with
all returns, you could catch the undocumented _DefGen_Return, do your
processing and then re-raise it but that's even more ugly.  So I'm just
trying to offer a clean way to always get hold of the deferred and be able
to consistently process it using code in the same file (or class, given a
self) as foo.


More information about the Twisted-Python mailing list