问题描述
我有以下简单的脚本:
#!/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'
def finished(results):
print 'finished', results
tasks = []
d = getPage('thiswontwork').addCallback(success).addErrback(error)
tasks.append(d)
dl = defer.DeferredList(tasks)
dl.addCallback(finished)
reactor.run()
这将产生以下输出:
error
finished [(True, None)]
由于getPages任务失败并调用它的错误回调,因此我希望此错误任务返回false.有人可以解释这种行为吗?
I would expect this error task to return a false since the getPages task fails and calls it's error callback. Can anybody explain this behaviour?
推荐答案
让我添加一个超出您选择的答案的想法:
Let me add a thought beyond what you selected as the answer:
在您的问题中,您打印了调用deferred(list)回调(finished
)的参数,并且您注意到您希望它是false
(由于之前发生的错误)
In your question you print the parameter that your deferred(list) callback(finished
) is called with, and you're noting that you would expect it to be false
(because of the error happening prior)
这种期望表明您对延期的思考会混淆您.
That expectation suggests your thinking about deferreds in a way thats going to confuse you later.
让我看看是否可以分开...
Let me see if I can break this apart...
(这里有很多细节,我会尽力而为)
(There are a lot of details and subtly in this stuff, I'm going to try my best)
推迟的时间是:
- 函数回调队列
- 其中,对于队列中的每个步骤",都存储了一个
callback
和errback
函数回调-
addCallbacks
(请注意其复数形式)可让您同时添加回调和errback -
addCallback
添加一个回调(并将errback设置为跳到队列中的下一个条目) -
addErrback
添加一个errback(并将回调设置为跳到队列中的下一个条目) -
addBoth
添加一个函数作为errback和回调(...,这意味着它需要弄清楚为什么通过arg调用它的原因与它调用了
-
- a queue of function callbacks
- Which, for each 'step' in the queue there is both a
callback
and anderrback
function callback storedaddCallbacks
(note its plural) lets you add both the callback and the errback at onceaddCallback
adds a callback (and sets the errback to skip to the next entry in the queue)addErrback
adds a errback (and sets the callback to skip to the next entry in the queue)addBoth
add a function as both the errback and the callback (... which means it needs to figure out why its being called via the arg its called with
从 krondo的第7部分中绘制:(...扭曲的文档也具有画好)
Drawing from krondo's part 7: (...Twisted docs also have a good drawing)
如果将一个函数作为callback
添加到延迟对象,并且该延迟对象已达到其触发"点,则该步骤之前的步骤成功返回,则延迟对象将先前成功函数的返回值传递给callback
中定义的功能.
If a function is added to a deferred as a callback
and the deferred has reached the point in its 'firing' that the step before this one return successfully, the deferred with pass the return value of the previous successfully function to the function defined in the callback
.
如果将函数作为errback
添加到延迟项,并且该延迟项已达到其触发"点,则上一步将返回Failure
对象(或引发异常,将其扭曲转换为Failure
对象),则errback
将与该Failure
对象一起调用. 注意!!如果错误返回不返回Failure
,则推迟执行的错误会转回到调用callback
链,而不是错误返回!
If a function is added to a deferred as a errback
and the deferred has reached the point in its 'firing' where the previous step returned a Failure
object (or raised an exception, which twisted transforms into a Failure
object), then the errback
will be called with that Failure
object. Note! if the errback doesn't return a Failure
, the deferred will flip back to calling the callback
chain, not the errback!
从 Krondo的第9部分中提取:
虽然这一切似乎有点让人费解,但它可以让您实现延迟延迟的错误恢复之类的事情,这确实很有帮助(而且并非在协议设计中很常见)
While this all may seem like a bit of a brain-twister, it lets you implement things like error-recovery mid-deferred, which can be really helpful (and not all that uncommon in protocol design)
IE :(从 Krondo的第9部分中提取):
I.E: (Drawing from Krondo's part 9):
综上所述,您认为我希望这个错误任务返回一个假"的错误是,finished
不会被任何类型的错误任务调用,而延迟任务会调用它,并且仅在成功时调用(因为仅将其作为callback
而不是作为errback
加载到延期中)
To put this all together, the error in your thought of "I would expect this error task to return a false" is that finished
isn't called by any sort of error task, its called by the deferred, and on top of that It's only called on success (because its only loaded into the deferred as a callback
not as an errback
)
如果您已将finished
函数同时作为errback
和callback
加载(也许通过addBoth
),并且您已按照答案的建议通过返回以下内容来转发errback的返回状态: Failure
对象,从技术上讲,您的finished
函数仍然不会通过 False
!它会收到一个Failure
对象.
If you had loaded the finished
function as both an errback
and a callback
(perhaps via addBoth
), and you had followed the answers advice to forward the return-state of the errback via returning the Failure
object, your finished
function still technically wouldn't be passed False
! it would receive a Failure
object.
...就像我说的那样,在这些东西中有很多巧妙的地方...
... Like I said, lots of subtly in this stuff ...
如果您发现其中任何一项有帮助(...,或者即使您没有这样做-我也不如作家那样出色),那么您真的应该仔细阅读科隆(Krondo)的扭曲介绍.我认为在阅读该指南后,您会发现很多这样的焦点.
If you find any of this helpful (... or even if you don't - I'm not as good of a writer), you really should dig through Krondo's twisted introduction. I think you'll find a lot of this snaps into focus after going through that guide.
这篇关于Python DeferredList回调在延迟引发错误时报告成功的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!