Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5120081
  • 博文数量: 921
  • 博客积分: 16037
  • 博客等级: 上将
  • 技术积分: 8469
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-05 02:08
文章分类

全部博文(921)

文章存档

2020年(1)

2019年(3)

2018年(3)

2017年(6)

2016年(47)

2015年(72)

2014年(25)

2013年(72)

2012年(125)

2011年(182)

2010年(42)

2009年(14)

2008年(85)

2007年(89)

2006年(155)

分类: Python/Ruby

2012-04-07 10:43:13

   在《使用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:
阅读(1730) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~