Twisted:如何在延迟时中断回调链
Twisted: How to interrupt callback chain on deferred
我的问题:我有一个带有回调和错误反馈的延迟。我需要在特定的错误返回后停止该过程。换句话说,如果调用了 errback 的特定函数,我需要获取它的 returns 并且不要处理以下回调。
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,erro”,而不是“1,ok”。
我现在的 return:
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
我该怎么做?
提前致谢
这是一个非常有趣的问题。 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 的精神。
我的问题:我有一个带有回调和错误反馈的延迟。我需要在特定的错误返回后停止该过程。换句话说,如果调用了 errback 的特定函数,我需要获取它的 returns 并且不要处理以下回调。
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,erro”,而不是“1,ok”。
我现在的 return:
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
我该怎么做?
提前致谢
这是一个非常有趣的问题。 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 的精神。