Фатальные ошибки и отсрочки в Twisted, остановка отсроченного - PullRequest
1 голос
/ 28 апреля 2011

У меня проблема, с обычной попыткой, за исключением блоков в python, вы можете просто вернуть, если есть фатальная ошибка, например ...

try:
    logon()
except 404_Error:
    retry_logon(try = 2)

except AuthenticationProblem:
    error_label.SetText( "You password or username was wrong. Make sure that CAPS LOCK key is not on." )
    return#nothing more we can do here
else:
    #display user information or whatever

Так как же это сделать с отложенными, если я просто верну его, он перейдет к выполнению обратных вызовов, думая, что ошибка обработана, но как мне сообщить пользователю, что что-то пошло не так, и разрушить цепочку вниз по реке.

==== Обновление ===

мг спасибо за помощь, но она не сработала, даже с фатальной ошибкой отсрочка все еще возвращается к обратным вызовам после слов

from twisted.internet import reactor
from twisted.internet.defer import Deferred as D

class NonFatalError(Exception):
    'non fatal error'
class FatalError(Exception):
    'fatal error'
def c(s):
    print "Callback called"
    print "Data Received: %s" % s
def e(f):
    print "Errorback Called"
    print "Error Type: %s" % type(f)
    print "Traceback"
    f.printTraceback()
    print "======================================="
    f.trap(NonFatalError)
    return "Error Handled"
def e_fatal(f, d):
    print "Errorback Called"
    print "Error Type: %s" % type(f)
    print "Traceback"
    f.printTraceback()
    print "======================================="
    print "Fatal Error"
    f.trap(FatalError)
    return "Fatal Error... Crash and die. No more callbacks should be called."

def trigger():
    d.errback(FatalError("This error is fatal to the defer"))

if __name__ == "__main__":
    d = D()
    d.addErrback(e)
    d.addErrback(e_fatal, d)
    d.addCallback(c)
    d.addCallback(c)
    d.addCallback(c)
    d.addCallback(c)
    reactor.callLater(3, trigger)
    reactor.callLater(10, reactor.stop)
    reactor.run()

    raw_input("Done.")

1 Ответ

2 голосов
/ 28 апреля 2011

Хорошо, совершенно новый ответ, чтобы лучше объяснить, как работают deferreds . Вы должны думать, по крайней мере, я, поток программы, как конечный автомат. Успех или неудача подобны вводу этой машины, которая потенциально может изменить состояние. В вашем случае у вас есть два состояния: зарегистрировано и не зарегистрировано, и три входа: успешный вход в систему, неправильная аутентификация и не удалось войти в систему из-за проблем с сервером. Восстанавливается только один из этих входных данных, в случае, если сервер не смог войти в систему пользователя из-за той же странной проблемы, и в этом случае вы можете восстановить проблему, повторив вход в систему. Вот новый код:

import sys
from twisted.internet import reactor, defer


class FourOhFourError(Exception):
    pass


class AuthenticationError(Exception):
    pass


def logon(retry=3, success=2, wrong_auth=0):
    # do stuff
    d = defer.Deferred()
    # not_found is the only error recoverable
    d.addErrback(not_found, retry, success)
    if wrong_auth:
        reactor.callLater(0, d.errback, AuthenticationError("wrong auth"))
    else:
        if success == 0:
            reactor.callLater(0, d.callback, "Mario")
        else:
            reactor.callLater(0, d.errback, FourOhFourError("Not found"))
    return d


def not_found(failure, retry, success):
    failure.trap(FourOhFourError) # this is superfluous here
    print failure.getErrorMessage()
    if retry == 0:
        raise AuthenticationError("Max retries")
    # do stuff
    print "retring..."
    d = defer.Deferred()
    d.addCallback(logon, success-1)
    reactor.callLater(1, d.callback, retry-1) # not really clean here
    return d


def wrong_auth(failure):
    failure.trap(AuthenticationError) # this is superfluous here
    # do stuff
    print "something goes wrong"
    print failure.getErrorMessage()


def loggedIn(user):
    print "hello %s" % user


def stop(_):
    reactor.stop()


d = logon(*map(int, sys.argv[1:]))
d.addCallbacks(loggedIn, wrong_auth)
d.addBoth(stop)
reactor.run()

Вызвать код с тремя параметрами: максимальное количество повторных попыток, при которых повторная попытка система должна войти в систему пользователя, а третий - логическое значение, указывающее правильность учетных данных пользователя. Попробуйте следующие вызовы: 0 0 1, 3 2 0, 3 4 0.

Надеюсь, этот пример более объяснительный.

...