Twisted上的生成器回调延迟

时间:2018-06-24 01:38:35

标签: python callback generator twisted deferred

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

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链?

我是一个扭曲的初学者,所以也许我想做的是一种不好的做法,甚至是不可能/真的很难做到的,请告诉我是这样的情况。预先感谢!

1 个答案:

答案 0 :(得分:0)

如果我正确理解,为了获得诸如从注释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)