我是新来的扭曲并且遇到以下脚本的问题。
当我运行以下内容时:
#!/usr/bin/env python
from twisted.internet import defer
from twisted.web.client import getPage, reactor
def success(results):
print 'success'
def error(results):
print 'error'
return results
def finished(results):
print 'finished'
reactor.stop()
tasks = []
d = getPage('thiswontwork').addCallback(success).addErrback(error)
tasks.append(d)
dl = defer.DeferredList(tasks)
dl.addCallback(finished)
reactor.run()
我得到以下输出:
error
finished
Unhandled error in Deferred:
Unhandled Error
Traceback (most recent call last):
Failure: twisted.internet.error.ConnectionRefusedError: Connection was refused by other side: 61: Connection refused.
我的问题是,当我似乎在错误回调中发现错误时,为什么会出现未处理的错误?
答案 0 :(得分:4)
问题在于,在error
def中,您返回result
,如果它被错误调用,则返回Failure
个对象,并返回Failure
个对象是重新提高错误状态的两个标准之一。请参阅krondo's twisted intro - part 9中的以下简介:
是的,如果你改变的话,试试吧:现在,在同步代码中,我们可以使用raise关键字“重新引发”异常,而不使用任何参数。这样做会引发我们正在处理的原始异常,并允许我们对错误采取一些操作而不完全处理它。事实证明我们可以在错误中做同样的事情。如果出现以下情况,延迟将认为回调/错误失败:
- 回调/错误引发任何类型的异常,或
- callback / errback返回一个Failure对象。
由于errback的第一个参数始终是Failure,因此errback可以在执行它想要执行的任何操作后通过返回其第一个参数来“重新引发”异常。
def error(results):
print 'error'
return results
到
def error(results):
print 'error'
return
你不会再次提高错误状态,所以它不会渗透到反应堆中,并且不会导致让你烦恼的追溯。
P.S。我不能推荐krondo's twisted introduction!它可能真的很长,但如果你能够通过它,你真的能够生成扭曲的代码,这些行为不会成为一个谜。
P.P.S我看到你之前有关于延迟的SO问题(Python DeferredList callback reporting success when deferreds raise error),这可能就是你用这种方式构建代码的原因。我认为你可能对defs中涉及的def(特别是errbacks)的返回值/回调值有一个根本的误解。查看part 9(尽管您可能需要备份part 7或甚至更早来跟踪它)krondo,但它确实应该有助于清理。