2016-05-25 2 views
2

Моя проблема: у меня есть отсрочка с обратными вызовами и ошибками. Мне нужно остановить процесс после определенного отказа. Другими словами, если вызывается определенная функция errback, мне нужно получить ее возврат и НЕ обрабатывать следующие обратные вызовы.Twisted: Как прервать цепочку обратного вызова по отложенному

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- процесса, мне нужно baypass -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 

Как я могу это сделать

заранее спасибо

+0

Это действительно хороший вопрос, я бы хотел услышать, есть ли у кого-нибудь ответ на этот вопрос. Здесь есть интересное обсуждение этой проблемы: http://stackoverflow.com/questions/9295359/stopping-twisted-from-swallowing-exceptions Я не уверен, что то, что вы хотите сделать, возможно. В принципе, если вы хотите полностью прекратить выполнение, почему вы возвращаете результат из-за ошибки? Возможно, вы просто можете вызвать ошибку в errback? Это прекратит обработку. Если вы не повышаете ошибку, Twisted предполагает, что вы хотите двигаться дальше, и она движется дальше. –

+0

Я использую цепочку обратного вызова для управления и проверки результатов запроса http get (вызов веб-службы REST) ​​последовательно. Когда результат - это то, что я ожидаю, процесс продолжается. В противном случае я вызываю отказ вызова errback (метод, который возвращает измененный ответ). Но, если в последовательности вызовов одна неудача, то следующие не имеют значения. Спасибо @PawelMiech за подсказку. –

ответ

0

это действительно интересно Ques? Тион. Twisted не дает документально подтвержденного API для изменения цепочки обратного вызова после возникновения ошибки. Если вы действительно хотите прерывать обработку в errback, вы всегда можете вызывать ошибку, а не захватывать ее.

Однако, если вы действительно хотите удалить все обратные вызовы из 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' 

Это работает, как вы хотите, чтобы работать, но, кажется, немного Hacky, так что я был бы рад прочитать, что думают другие пользователи. Здесь обсуждается более подробно: Stopping Twisted from swallowing exceptions Обсуждение там говорит о том, что то, что вы пытаетесь сделать, несколько противоречит духу Twisted.

+0

Спасибо @PawelMiech. Работает отлично. –

Смежные вопросы