[Twisted-Python] deferredGenerator or inlineCallbacks

Justin Warren daedalus at eigenmagic.com
Mon Jan 14 19:53:07 MST 2008


On Tue, 2008-01-15 at 12:34 +1100, Justin Warren wrote:
> Hi folks,
> 
> I think I have a fundamental misunderstanding of how deferredGenerator
> (or inlineCallbacks for Python2.5) work.
> 
> What I *want* to do, is something like this:
> 
> aValue = MyObject.get_a_value()

Aha!

Replying to my own post, I know, but I think I found the insight that
was preventing me from grokking this mechanism.

Adding @defer.deferredGenerator or @defer.inlineCallbacks 'turns on' the
inline callback mechanism *within that function*. You can then use the
inline yield syntax to perform sequential operations that are actually
asynchronous things that 'wait' for the operation to complete before
continuing to the next bit of code.

So, to do what I wanted to do, I needed to think about things
differently. Here's a concrete example:

I wanted to use the ZAPITool.zapi_request() function from my ModiPY code
to query a NetApp filer via its ZAPI (XML over HTTP) protocol. This
function returns a Deferred() that will .callback() or errback() when a
result is available.

So, I want to fetch the version of the filer OS. Normally, I'd use
something like this:

zpt = ZAPITool()
d = zpt.zapi_request('<system-get-version/>')

def got_result(result):
    print "Got a result:", result
    # Do something with the result

d.addCallback( got_result )

Which is messy, verbose, and annoying.

I can do this using inlineCallbacks thusly:

@defer.inlineCallbacks    # turn on inline callback functionality
def do_some_inline_callback_stuff():
    zpt = ZAPITool()
    result = yield zpt.zapi_request('<system-get-version/>')
    print "Got a result:", result
    # Do something with the result
    ...

    # Do another fetch
    result = yield zpt.zapi_request('<options-list-info/>')
    print "Filer options are:", result

    # and so on


w00t!

Note that you cannot

    return result

from within do_some_inline_callback_stuff(), because this is actually a
generator now, since it contains a yield.

This is quite neat stuff.. though it feels a bit sneaky and magical.

-- 
Justin Warren <daedalus at eigenmagic.com>




More information about the Twisted-Python mailing list