Twisted 中的致命错误和延迟,停止延迟

发布于 2024-11-03 20:40:03 字数 1690 浏览 1 评论 0原文

我有一个问题,在 python 中使用正常的 try except 块,如果出现致命错误,您可以只返回,例如...

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

那么如何使用延迟执行此操作,如果我只是返回它会执行回调,认为错误已处理但是我如何通知用户出了问题并破坏了下游链。

====更新===

mg感谢您的帮助,但它不起作用,即使出现致命错误,延迟仍然返回到回调后记

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.")

I have a problem, with normal try except blocks in python you can just return if there is a fatal error, ex...

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

So how do this with deferreds, if I just return it goes onto execute the callbacks thinking the error is handled but how do I inform the user something went wrong and destroy the down river chain.

==== Update ===

mg thanks for the help but it didn't work, even with a fatal error the defer still returns to the callbacks afterwords

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.")

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

江南烟雨〆相思醉 2024-11-10 20:40:03

好的,一个全新的答案可以更好地解释 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 13 2 03 4 0

我希望这个例子更能说明问题。

Ok, a whole new answer to explain better how deferreds work. You should think, at least I do, the flow of the program as a state machine. A success or a failure is like an input of that machine that, potentially, change the state. In your case you have two states, logged and non logged, and three inputs: successfully logged in, wrong authentication and could not logged for server problems. Only one of this inputs is recoverable, the case the server could not login the user for same strange problem and in this case you can recover the problem retrying the login. Here the new code:

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()

Invoke the code with three parameters: the maximum number of retries, at which retry the system should login the user and the third is a boolean indicating the correctness of the user credentials. Try the following invocations: 0 0 1, 3 2 0, 3 4 0.

I hope this example is more explicative.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文