2016-05-25 12 views
2

Mein Problem: Ich habe eine aufgeschoben mit Rückrufen und Fehler. Ich muss den Prozess nach einem bestimmten Fehler stoppen. Mit anderen Worten, wenn eine spezifische Funktion von errback aufgerufen wird, muss ich ihre Rückgaben erhalten und NICHT die folgenden Rückrufe verarbeiten.Twisted: Wie Callback-Kette auf verzögerte unterbrochen

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) 

Dieser Code ist eine einfache Version als spiegelt, was ich brauche. Nach -A- Prozess, ich brauche -B- und -C-, und am Ende die Antwort "0, erro", nicht „1, ok‘

Meine heutige Rückkehr nach baypass.

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 

und ich will:

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 

Wie kann ich dies tun

Vielen Dank im Voraus

+0

das ist eine wirklich gute Frage, ich würde gerne hören, ob jemand dafür eine Antwort hat. Es gibt eine interessante Diskussion dieses Problems hier: http://stackoverflow.com/questions/9295359/stopping-twisted-from-swallowing-exceptions Ich bin mir nicht sicher, ob was Sie tun möchten, ist möglich. Grundsätzlich, wenn Sie die Ausführung beenden wollen, warum geben Sie das Ergebnis von Fehler zurück? Vielleicht können Sie Fehler einfach in errback erhöhen? Dies wird die Verarbeitung stoppen. Wenn du keinen Fehler erhöhst, nimmt Twisted an, dass du weitergehen willst und es weitergeht. –

+0

Ich verwende Callback-Kette, um die Ergebnisse der http-get-Anforderung (REST-Web-Service-Aufruf) in Serie zu steuern und zu validieren. Wenn das Ergebnis das ist, was ich erwarte, wird der Prozess fortgesetzt. Wenn nicht, erhalte ich den Fehler, den Fehler zu rufen (eine Methode, die die Antwort zurückgibt). Aber wenn in der Reihenfolge der Anrufe eine fehlschlägt, sind die folgenden irrelevant. Danke @PawelMiech für den Tipp. –

Antwort

0

das ist eine wirklich interessante ques ist? tion. Twisted gibt keine dokumentierte API zum Ändern der Rückrufkette nach dem Auftreten eines Fehlers. Wenn Sie die Verarbeitung im Fehlerback wirklich unterbrechen möchten, können Sie den Fehler immer erhöhen, anstatt ihn zu überfüllen.

Wenn Sie jedoch wirklich alle Rückrufe von Deferred unter bestimmten Bedingungen entfernen möchten, können Sie einfach Hack verwenden. Rückrufe werden als einfache Objektattribute beibehalten, siehe hier: https://github.com/twisted/twisted/blob/twisted-16.2.0/twisted/internet/defer.py#L288 Wenn Sie dieses Attribut einfach auf eine leere Liste zurücksetzen, werden alle Rückrufe entfernt und die Verarbeitung wird gestoppt.

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

Dies funktioniert, wie Sie es, arbeiten möchten, aber es scheint ein wenig hacky so würde ich glücklich sein, zu lesen, was andere User. Es gibt mehr Diskussion dieses Problems hier: Stopping Twisted from swallowing exceptions Diskussion dort schlägt vor, dass das, was Sie versuchen, ist etwas gegen den Geist von Twisted.

+0

Danke @PawelMiech. Funktioniert gut. –