Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to catch exceptions from a twisted inlineCallbacks decorated function?

I am getting started with twisted as one of the libs I'll be using depends on it. In an early test I am confused about how to catch an exception thrown in a function like this:

@defer.inlineCallbacks
def read_input_status(self, address, length, callback):
    assert callback
    # ...

If callbackis None an AssertionError is thrown, so I tried to see it... The function is called like this:

def cb():
    pass
def eb():
    pass

d = task.deferLater(reactor, 1, client.read_input_status, 0x0000, 8, None)
d.addCallback(cb)
d.addErrback(eb)

I'm calling deferLater here on purpose to be able to deal with errors, as I understood that's not possible when using `callLater'. But my errback is never called.

What's weird is that when trying to debug and looking at the twisted lib's code I think I've seen a reason, why my errback is without effect. My decorated generator function (argument g below) is called by twisted's defer._inlineCallbacks implementation like this (breviated):

def _inlineCallbacks(result, g, deferred):
    # ...
    while 1:
        try:
            # ...
            result = g.send(result)
        except:
            deferred.errback()
            return deferred

I do see my exception pop up in the last section, where a deferred's errback is then called. But: that is not my deferred... If I go up one call in the debugger's call hierarchy, I see which deferred object is actually passed to _inlineCallbacks:

def unwindGenerator(*args, **kwargs):
    # ...
    return _inlineCallbacks(None, gen, Deferred())

Am I mistaken or is this simply a new object, empty, plain, without an callbacks/errbacks attached?

Sorry for this lengthy elaboration. Couldn't find anything immediately related, except for this SO post where I could not directly see how it solves my issue.

Thanks a lot.

[UPDATE] Please see this gist for working sample code (Python 2.7.6, Twisted 13.2.0).

like image 730
mikep Avatar asked Oct 21 '22 18:10

mikep


1 Answers

Figured it out after rereading the docs about Twisted Deferred callbacks and errbacks. The issue with the code above and in the linked gist are the missing arguments for callback and errback. If I replace what's written above with the following code, the exception is caught fine and notified via errback as expected:

def cb(result):
    pass
def eb(failure):
    pass
like image 144
mikep Avatar answered Oct 23 '22 10:10

mikep