简体   繁体   English

Twisted上的生成器回调延迟

[英]Generator callbacks on Twisted deferred

I'm trying to jump around in the callback chain for a Twisted deferred, using callbacks that return generators. 我正在尝试使用返回生成器的回调在回调链中跳转以获取Twisted延迟。 Consider the following snippet: 考虑以下代码段:

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')

The output for that is 的输出是

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

However, if the yield is uncommented from callback_one I get only 但是,如果yield不从callback_one注释,我只会得到

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

If I understand correctly, what's happening is that the first callback returns a generator which is not evaluated until it's too late, the exception is not caught and therefore the errback is not invoked. 如果我理解正确,那么发生的情况是第一个回调返回一个生成器,该生成器直到为时已晚才被评估,没有捕获到异常,因此不会调用errback。

To sum up, the question is: if a callback returns a generator, how can I raise an exception from it in a way that is caught by the deferred object so the errback chain is triggered? 综上所述,问题是:如果回调返回了生成器,如何以延迟对象捕获的方式从中引发异常,从而触发errback链?

I'm a Twisted beginner so perhaps what I'm trying to do is a bad practice or even impossible/really hard to achieve, please let me know if that's the case. 我是一个扭曲的初学者,所以也许我想做的是不好的做法,甚至是不可能/很难做到的,请告诉我是这样的情况。 Thanks in advance! 提前致谢!

If I understand correctly, to get the results such as the one you get from commenting out yield , you need to invoke the generator. 如果我正确理解,要获得诸如从yield注释掉得到的结果之类的结果,您需要调用生成器。 To do that you could create another function that just executes the generator and make a minor change to your main function: 为此,您可以创建另一个函数,该函数仅执行生成器并对主函数进行较小的更改:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM