首页 > 解决方案 > Twisted deferred 上的生成器回调

问题描述

我正在尝试使用返回生成器的回调在 Twisted deferred 的回调链中跳转。考虑以下代码段:

from twisted.internet import defer

def callback_one(result):
    print('Callback one: got "{}", will raise ZeroDivisionError'.format(result))
    raise ZeroDivisionError
    # yield

def errback_two(failure):
    print('Errback two: handled "{}", recovering'.format(failure.type))
    return 'recovered'

def callback_three(result):
    print('Callback three: got "{}"'.format(result))
    return 'Final result'

if __name__ == '__main__':
    d = defer.Deferred()
    d.addCallback(callback_one)
    d.addErrback(errback_two)
    d.addCallback(callback_three)
    d.callback('First result')

输出是

Callback one: got "First result", will raise ZeroDivisionError
Errback two: handled "<class 'ZeroDivisionError'>", recovering
Callback three: got "recovered"

但是,如果未从我那里得到yield注释callback_one

Callback three: got "<generator object callback_one at 0x104603af0>"

如果我理解正确,发生的事情是第一个回调返回一个生成器,直到为时已晚才评估该生成器,不会捕获异常,因此不会调用 errback。

总而言之,问题是:如果回调返回一个生成器,我如何以被延迟对象捕获的方式从中引发异常,从而触发 errback 链?

我是一名 Twisted 初学者,所以也许我正在尝试做的是一种不好的做法,甚至是不可能/真的很难实现,如果是这样,请告诉我。提前致谢!

标签: pythoncallbackgeneratortwisteddeferred

解决方案


如果我理解正确,要获得诸如注释掉的结果yield,您需要调用生成器。为此,您可以创建另一个仅执行生成器的函数并对您的主函数进行微小的更改:

def exec_gen(gen):
    """
    Execute the generator
    """
    for x in gen:
        print(x)
# ...

if __name__ == '__main__':
    d = defer.maybeDeferred(exec_gen, callback_one('First result'))
    d.addErrback(errback_two)
    d.addCallback(callback_three)

推荐阅读