twisted中DeferredList介绍

 在《使用twisted编写异步服务器》中,我们学习了使用defer来处理异步事件。使用defer后程序不等待数据返回继续其他操作,待数据就绪后再通过回调函数来处理数据。前面提到的都是等待单数据,但有时需要多份数据全部返回后才能继续操作,例如取用户的不同信息。遇到这种情况时就需要祭出DeferredList对象。
    Deferredlist可以在列表中所有deferred对象就绪后执行指定回调函数,从本质上来说它返回了一个新的deferred对象。我们来看Deferredlist的初始化:
    DeferredList(deferrlist, fireOnOneCallback=0, fireOnOneErrback=1, consumeErrors=1).addCallback(deferrlist_suc).addErrback(deferrlist_suc)
    deferrlist: 其所需等待的defer对象列表
    fireOnOneCallback:deferrlist列表中任一defer对象callback后,DeferredList就回调callback
    fireOnOneErrback: deferrlist列表中任一defer对象errback后,如果deferr对象未指定errback,DeferredList就回调errback
    consumeErrors:deferrlist列表中任一defer对象执行过程中发生错误后,如果deferr对象未指定errback, DeferredList就回调errback
  
    下面是使用DeferredList一个简单例子,它定义了包括三个defer对象的DeferredList,每个defer对象定义了自己的回调函数并使用callback返回。运行该例子可以看到回调先执行defer_suc函数,然后以它的返回结果为参数执行defer_suc函数。   通过打印的结果可以看到deferrlist_suc 第一个参数result是一个二元元组列表, 列表中的每个元组对应于每个deferr的返回值,元组的第一项为True或False,用于说明返回是否为failure对象,第二项为对应的值。关于该元组项我们后面会进一步说明。大家可能注意到defer_suc和deferrlist_suc函数我都指定了suc标记,该标记是用于识别函数有callback还是errback进入,这样对一个defer对象可以使用同一个函数来处理callback和errback。
from twisted.internet.defer import Deferred, maybeDeferred, DeferredList
from twisted.internet import defer
from twisted.internet import reactor
from twisted.python import failure
import sys, os

def defer_suc(result, suc):
    return result + ' defersuc'

def deferrlist_suc(result, suc):
    print result

deferrlist = []
for x in range(3):
    d = defer.Deferred()
    d.addCallback(defer_suc, True).addErrback(defer_suc, False)
    deferrlist.append(d)

DeferredList(deferrlist, fireOnOneErrback=1, consumeErrors=1).addCallback(deferrlist_suc, True).addErrback(deferrlist_suc, False)

for x in deferrlist:
    x.callback('a')


   前面我们对每一个deferr都指定了其回调函数defer_suc,其实这个指定并不是必须的。在为deferr指定回调函数时,它的callback和errback由指定回调执行,否则所有信息都将直接进入到DeferredList的回调函数中。这里需要注意的是当fireOnOneErrback为真时如果deferr未指定errback回调,该deferr的errback都将会导致DeferredList的errback的执行;当fireOnOneErrback为假时,无论deferr是否指定了errback回调,Deferredlist都是由callback回调(不考虑consumeErrors)。下面的例子中 第一次deferrlist_suc的第二个参数为False,第二次为True, 分别表示由errback和callback返回。

for x in range(3):
    deferrlist.append(defer.Deferred())

DeferredList(deferrlist, fireOnOneErrback=1, consumeErrors=1).addCallback(deferrlist_suc, True).addErrback(deferrlist_suc, False)

for x in deferrlist:
    x.errback('a')

for x in range(3):
    deferrlist.append(defer.Deferred())

DeferredList(deferrlist, fireOnOneErrback=1, consumeErrors=1).addCallback(deferrlist_suc, True).addErrback(deferrlist_suc, False)

for x in deferrlist:
    x.errback('a')  

         
   前面我们提到了deferrlist_suc中的result为一个二元元组列表, 元祖的第一项为True或False,用于说明返回是否为failure对象,第二项为对应的值。 那么在下面的例子中deferrlist_suc会输出什么呢?

def defer_suc(result, suc):
    return result

def deferrlist_suc(result, suc):
    print result

deferrlist = []
for x in range(3):
    d = defer.Deferred()
    d.addCallback(defer_suc, True).addErrback(defer_suc, False)
    deferrlist.append(d)

DeferredList(deferrlist, consumeErrors=1).addCallback(deferrlist_suc, True).addErrback(deferrlist_suc, False)

deferrlist[0].callback('a')
deferrlist[1].errback('a')
deferrlist[2].callback('a')   

   result中三个对象一模一样是否让你疑惑,为什么第二个deferr对象明明是errback,元祖第一项还是True呢。 因为deferr对象指定了errback回调函数,在errback发生时,

defer_suc函数就已经将错误吞掉,deferrlist_suc函数看到的都只是正常的返回而已,如果需要将err带入,即让元祖的第一项为False, 那么defer_suc函数返回的对象必须为一个failuer对象

    def defer_suc(result, suc):
        return result if suc else failure.Failure(result, str)


    
    最后一个问题:如果deferr的回调函数再加入deferrlist之后在指定会如何?根据文档描述,deferr指定的回调是否执行取决于其在回调前或后,如果在会掉前指定的话,该回调函数生效。但我测试时发现无论回调的指定在回调前或后,指定的回调函数都没有执行。 但无论如何请不要将deferr加入到deferrlist后为其指定回调函数,这将导致结果的

from:

http://hi.baidu.com/xjtukanif/blog/item/4849733c264a303670cf6ccb.html

分享到: 微信 更多