Python DeferredList回调在延迟引发错误时报告成功 [英] Python DeferredList callback reporting success when deferreds raise error

查看:132
本文介绍了Python DeferredList回调在延迟引发错误时报告成功的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下简单的脚本:

#!/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)

推迟的时间是:

  1. 函数回调队列
  2. 其中,对于队列中的每个步骤",都存储了一个callbackerrback函数回调
    • addCallbacks(请注意其复数形式)可让您同时添加回调和errback
    • addCallback添加一个回调(并将errback设置为跳到队列中的下一个条目)
    • addErrback添加一个errback(并将回调设置为跳到队列中的下一个条目)
    • addBoth添加一个函数作为errback和回调(...,这意味着它需要弄清楚为什么通过arg调用它的原因与它调用了
  1. a queue of function callbacks
  2. Which, for each 'step' in the queue there is both a callback and and errback function callback stored
    • addCallbacks (note its plural) lets you add both the callback and the errback at once
    • addCallback 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函数同时作为errbackcallback加载(也许通过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 ...

如果您发现其中任何一项有帮助(...,或者即使您没有这样做-我也不如作家那样出色),那么您真的应该仔细阅读

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回调在延迟引发错误时报告成功的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆