Хорошо, совершенно новый ответ, чтобы лучше объяснить, как работают 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
.
Надеюсь, этот пример более объяснительный.