Twisted中的inlineCallback对象实现

综合了别人写的两篇文章
inlineCallback:总体流程
图片
Python中的协程实现,大都是这个流程,比如,tornado.gen(务必阅读)。

inlineCallbacks只是一个确保返回生成器的异常处理,最终返回一个生成器:
处理嵌套的思路是:如果遇到内层是未完成的deferred,就将自己添加到内层deferred回调链的结尾
和处理嵌套Deferred的思路类似

def inlineCallbacks(f):
    @wraps(f)
    def unwindGenerator(*args, **kwargs):
    	gen = f(*args, **kwargs)
        return _inlineCallbacks(None, gen, Deferred())
    return unwindGenerator

inlineCallback代码简写,给出一个比较顺畅的流程,去除了failure判定,省略的地方用…代替

def _inlineCallbacks(result, g, deferred):
    waiting = [True, # waiting for result?
               None] # result

    while 1:
        try:
            # 每次启动生成器,它yield的值可以是:
            
            # 1.正常返回值:使用这个对象,继续启动生成器
            # 2.Deffered对象:已完成:那么使用结果,继续启动生成器
            #                未完成:那么给这个Deferred对象增加一个回调函数:当该Deferred对象完成时,使用其结果,继续启动生成器
            
            # 3.Failure对象,那么则将Failure对象封装的异常,传递给生成器
            #(不仅可以在生成器外部使用send()方法向其传值,还可以使用throw()方法向其传递异常)
            #         注意:当一个异步操作出现异常时,twisted会将异常信息封装进一个Failure对象
            # 简而言之就是:第一次是使用None启动生成器,之后每次都是使用上一次的结果启动生成器

            isFailure = isinstance(result, failure.Failure)
            if isFailure:
                result = result.throwExceptionIntoGenerator(g)
            else:
                result = g.send(result)
        except StopIteration as e:
            # 当生成器完成时,将deferred置为完成
            deferred.callback(getattr(e, "value", None))
            return deferred
        except _DefGen_Return as e:
            # 当通过returnValue()函数抛出_DefGen_Return异常时,那么从异常对象中提取值,并将其作为deferred的结果
            ...
            deferred.callback(e.value)
            return deferred
        except:
            # 启动生成器抛出其他异常时,将deferred置为失败
            deferred.errback()
            return deferred

        # 下面是生成器返回Deferred对象时的情形
        if _isinstance(result, Deferred):
            def gotResult(r):
                # 如果waiting[]为True,说明是result是个已经执行完毕的Deferred
                # 然后gotResult()是在result.addBoth()中被调用执行的
                # 那么通过waiting[1]保存结果,不进行递归,而是继续执行while循环
                if waiting[0]:
                    waiting[0] = False
                    waiting[1] = r
                else:
                    _inlineCallbacks(r, g, deferred)
                
            # 当用addBoth添加result Deferred对象的事件回调时
         
            # 如果该result是个已经执行完毕的Deferred,
            # 那么在addBoth()函数内将直接执行事件回调函数gotResult(),并走gotResult()的if语句,然后又继续回到顶部
            # 的while循环触发紧接着的下一个callback调用;
         
            # 如果该result是个未执行完毕的Deferred,
            # 那么添加该result的完成触发事件gotResult,
            # 并执行result.addBoth()下面的if语句,将waiting[]修改为False,
            # 然后return返回一个deferred,退出while循环。在接下来的时间中,
            # 一旦该result对于的callback执行完毕,将触发该result添加的gotResult()回调,
            # 并执行_inlineCallbacks(),然后继续执行callback链中的下一个callback调用。
                    
                    
                    
            # 如果内嵌deferred已经完成,那么会立刻激发gotResult()函数(addBoth会激发Deferred执行)
            #     gotResult()会将waiting[0]设置为False,waiting[1]保存result的结果,接下来会走 分支2;否则会走 分支1。
            result.addBoth(gotResult) ##result是一个Deferred对象,所以有addBoth方法

            # 分支1
            if waiting[0]:
                # 将waiting[0]置为False,当result完成时,会调用gotResult(),因为waiting[0]是False,所以会走其else分支,它会使用result的结果继续启动生成器
                waiting[0] = False
                return deferred
                
            # 能执行到这里,说明是个已经执行完毕的Deferred(addBoth()中直接执行了gotResult()函数)
            # 并将保存在waiting[1]中的结果保存到result中,然后回到顶部继续执行while循环
                
            # 分支2
            # result保存内层Deferred对象的结果
            result = waiting[1]
            
            # 重置状态,为下一轮while循环做准备
            waiting[0] = True
            waiting[1] = None

    return deferred
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值