【问题标题】:Twisted: How to interrupt callback chain on deferredTwisted:如何在延迟时中断回调链
【发布时间】:2016-05-25 15:23:54
【问题描述】:

我的问题:我有一个延迟回调和 errbacks。我需要在特定的错误返回后停止该过程。换句话说,如果调用了 errback 的特定函数,我需要获取它的返回并且不处理以下回调。

from twisted.internet import defer
from twisted.python import failure, util


class Test (object):

@classmethod
def handleFailure(self, f):
    print "handleFailure"
    f.trap(RuntimeError)
    return '0', 'erro'

@classmethod
def handleResult(self, result, message):
    print "handleResult of %s. Old results %s, %s: " % (message, result[0], result[1])
    return 1, 'ok'

@classmethod
def doFailure (self, result, message):
    print "handleResult of %s. Old results %s, %s: " % (message, result[0], result[1])
    raise RuntimeError, "whoops! we encountered an error"


@classmethod
def deferredExample(self):
    d = defer.Deferred()
    # 1o. call without error
    d.addCallback(Test.handleResult, 'call 1')
    # 2o. call without error
    d.addCallback(Test.handleResult, 'call 1')
    # 3o. call causes the failure
    d.addCallback(Test.doFailure,    'call 3')
    # the failure calls the error back 
    d.addErrback (Test.handleFailure) # - A -
    # after error back, the next call back is called
    d.addCallback(Test.handleResult, 'call 4')  # - B -
    # and the last call back is called   
    d.addCallback(Test.handleResult, 'call 5')  # - C -

    d.callback("success")
    return d.result[0], d.result[1]

if __name__ == '__main__': 
#    behindTheScenes("success")
    print "\n-------------------------------------------------\n"
    global num; num = 0
    tst = Test()
    rtn1, rtn2 = tst.deferredExample()
    print "RTN: %s %s" % (rtn1, rtn2)

此代码是一个简单的版本,它反映了我的需要。在 -A- 进程之后,我需要通过 -B- 和 -C-,最后,响应是“0,错误”,而不是“1,好的”。

我目前的回报:

handleResult of call 1. Old results s, u: 
handleResult of call 1. Old results 1, ok: 
handleResult of call 3. Old results 1, ok: 
handleFailure
handleResult of call 4. Old results 0, erro: 
handleResult of call 5. Old results 1, ok: 
RTN: 1 ok

我想要:

handleResult of call 1. Old results s, u: 
handleResult of call 1. Old results 1, ok: 
handleResult of call 3. Old results 1, ok: 
handleFailure
RTN: 0 erro

我该怎么做?

提前致谢

【问题讨论】:

  • 这是一个非常好的问题,我很想知道是否有人对此有答案。这里有一些关于这个问题的有趣讨论:stackoverflow.com/questions/9295359/…我不确定你想做的事情是否可行。基本上,如果您想完全停止执行,为什么要从 errback 返回结果?也许您可以简单地在 errback 中引发错误?这将停止处理。如果你不提出错误,Twisted 假设你想继续前进,它会继续前进。
  • 我正在使用回调链来控制和验证http get请求(REST Web服务调用)的结果。当结果符合我的预期时,该过程继续进行。如果不是,我会提出调用 errback 失败(返回修改后响应的方法)。但是,如果在调用序列中一个失败,以下是无关紧要的。感谢@PawelMiech 的提示。

标签: python twisted deferred


【解决方案1】:

这是一个非常有趣的问题。 Twisted 没有提供任何记录在案的 API 用于在发生错误后修改回调链。如果你真的想在 errback 中中断处理,你总是可以引发错误而不是捕获它。

但是,如果您真的想在某些情况下从 Deferred 中删除所有回调,您可以使用简单的 hack。回调作为简单对象属性保留在 Deferred 上,请参见此处:https://github.com/twisted/twisted/blob/twisted-16.2.0/twisted/internet/defer.py#L288 如果您只是将此属性重置为空列表,所有回调将被删除并停止处理。

@classmethod
def handleFailure(self, f, d):
    print "handleFailure"
    f.trap(RuntimeError)
    d.callbacks = []
    return '0', 'erro'

这可以按您的意愿工作,但似乎有点老套,所以我很乐意阅读其他用户的想法。这里有更多关于这个问题的讨论:Stopping Twisted from swallowing exceptions 那里的讨论表明你正在尝试做的事情在某种程度上违背了 Twisted 的精神。

【讨论】:

  • 谢谢@PawelMiech。工作正常。
  • 最好不要这样做,你最好按照errback链来这样做:return failure in handleFailure to follow the errback chain or return others to follow the callback chain
猜你喜欢
  • 1970-01-01
  • 2011-11-08
  • 1970-01-01
  • 2015-03-15
  • 1970-01-01
  • 2017-04-28
  • 2011-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多