twisted 提供了 deferred 机制,而关键点就是回调。通过查看deferred 源码 (version 8.2.0)我们可以 看到

deferred的addCallback是怎么工作的,以及相关的操作流程。 一个deferred 有一对回调链,一条处理正确的结果,一条处理错误的结果,addCallbacks 与 addCallback ,addBoth 函数则是向这对回调链里添加函数,addCallback 后,deferred 是怎么做的呢,我们看源码:

        

def addCallbacks(self, callback, errback=None,
                     callbackArgs=None, callbackKeywords=None,
                     errbackArgs=None, errbackKeywords=None):
        """Add a pair of callbacks (success and error) to this Deferred.

        These will be executed when the 'master' callback is run.
        """
        assert callable(callback)
        assert errback == None or callable(errback)
        cbs = ((callback, callbackArgs, callbackKeywords),
               (errback or (passthru), errbackArgs, errbackKeywords))
        self.callbacks.append(cbs)

        if self.called:
            self._runCallbacks()
        return self

def addCallback(self, callback, *args, **kw):
        """Convenience method for adding just a callback.

        See L{addCallbacks}.
        """
        
        return self.addCallbacks(callback, callbackArgs=args,
                                 callbackKeywords=kw)
             

addCallback第二个参数是要添加的函数,第三个参数是要传递给回调函数的参数,第四个是要传递给回调函数
的关键字,然后,addCallback里调用了addCallbacks 。 我们可以看到,在deferred初始化 时,这对回调链self.callbacks 是空的 

def __init__(self):
        self.callbacks = [] 
        if self.debug:
            self._debugInfo = DebugInfo()
            self._debugInfo.creator = traceback.format_stack()[:-1]
        cbs = ((callback, callbackArgs, callbackKeywords),
               (errback or (passthru), errbackArgs, errbackKeywords))
        self.callbacks.append(cbs)

 看addCallbacks源码,你会发现, 如果没有指定要添加的errback 时,errback 则是pass-through 的。这时,这对回调函数就会被添加到回调链的尾, 效果如图所示:

                                                            

                         

            当调用一个回调函数时,deferred 又会怎么做呢?假设当前调用的是 callback:

             

def callback(self, result):
        """Run all success callbacks that have been added to this Deferred.

        Each callback will have its result passed as the first
        argument to the next; this way, the callbacks act as a
        'processing chain'. Also, if the success-callback returns a Failure
        or raises an Exception, processing will continue on the *error*-
        callback chain.
        """
        assert not isinstance(result, Deferred)
        self._startRunCallbacks(result)
              看作者的注释,deferred 把上一个回调函数的结果result传递给 _startRunCallbacks:

def _startRunCallbacks(self, result):
        if self.called:
            if self.debug:
                if self._debugInfo is None:
                    self._debugInfo = DebugInfo()
                extra = "\n" + self._debugInfo._getDebugTracebacks()
                raise AlreadyCalledError(extra)
            raise AlreadyCalledError
        if self.debug:
            if self._debugInfo is None:
                self._debugInfo = DebugInfo()
            self._debugInfo.invoker = traceback.format_stack()[:-2]
        self.called = True
        self.result = result 
        if self.timeoutCall:
            try:
                self.timeoutCall.cancel()
            except:
                pass

            del self.timeoutCall
        self._runCallbacks()


                   但这时还没有真正调用了我们刚才添加的回调函数,在这个_startRunCallbacks 里是找不到回调链
“self.callbacks ”的字眼的。这个函数是“开始执行回调函数”,对执行之前处理了一些事务,但它最后调用了
_runCallbacks:

      

def _runCallbacks(self):
        if self._runningCallbacks:
            # Don't recursively run callbacks
            return
        if not self.paused:
            while self.callbacks:
                item = self.callbacks.pop(0) 
                callback, args, kw = item[   
                    isinstance(self.result, failure.Failure)] 
                args = args or ()            
                kw = kw or {}               

                try:
                    self._runningCallbacks = True
                    try:
                        self.result = callback(self.result, *args, **kw) 
                    finally:                                             
                        self._runningCallbacks = False                
                    if isinstance(self.result, Deferred):                
                        # note: this will cause _runCallbacks to be called
                        # recursively if self.result already has a result.
                        # This shouldn't cause any problems, since there is no
                        # relevant state in this stack frame at this point.
                        # The recursive call will continue to process
                        # self.callbacks until it is empty, then return here,
                        # where there is no more work to be done, so this call
                        # will return as well.
                        self.pause()
                        self.result.addBoth(self._continue)
                        break
                except:
                    self.result = failure.Failure()

        if isinstance(self.result, failure.Failure):
            self.result.cleanFailure()
            if self._debugInfo is None:
                self._debugInfo = DebugInfo()
            self._debugInfo.failResult = self.result
        else:
            if self._debugInfo is not None:
                self._debugInfo.failResult = None

       self.callbacks.pop(0)                                                       #弹出回调链里的第一对回调函数,
    callback, args, kw = item[   
                    isinstance(self.result, failure.Failure)]            #根据self.result是否为 failure.Failure类型,来选择回调函数
                                                                                     
     self.result = callback(self.result, *args, **kw)                #这才真正执行了回调函数并把执行结果 作为参数传递给下                                                                                            #一个回调函数


    通过作者的注释,我们可以看到,当执行完回调函数之后,
(1)若self.result 为deferred,即如果回调函数返回一个新的deferred,则当前的deferred(外部deferred)会

         暂停下来,去执行新的deferred(内部deferred)里的回调函数,直到内部deferred把控制权转交给外部  
         deferred,如图:

                            
        

              看代码:

                        self.pause()
                        self.result.addBoth(self._continue)
                     而addBoth会调用addCallbacks,  addCallbacks 则调用_runCallbacks,

def addBoth(self, callback, *args, **kw):
        """Convenience method for adding a single callable as both a callback
        and an errback.

        See L{addCallbacks}.
        """
        return self.addCallbacks(callback, callback,
                                 callbackArgs=args, errbackArgs=args,
                                 callbackKeywords=kw, errbackKeywords=kw)
  
def addCallbacks(self, callback, errback=None,
                     callbackArgs=None, callbackKeywords=None,
                     errbackArgs=None, errbackKeywords=None):
        """Add a pair of callbacks (success and error) to this Deferred.

        These will be executed when the 'master' callback is run.
        """
        assert callable(callback)
        assert errback == None or callable(errback)
        cbs = ((callback, callbackArgs, callbackKeywords),
               (errback or (passthru), errbackArgs, errbackKeywords))
        self.callbacks.append(cbs)

        if self.called:
            self._runCallbacks()
        return self


          调用顺序为:
          addBoth --> addCallbacks --> _runCallbacks, 如此递归执行。
(2)若self.result 不为deferred,则执行下一个回调函数,并把self.result 传递给下一个回调函数,直到self.result为              空。整个跟踪过程就到这里把!


     参考:         
        http://twistedmatrix.com/trac/browser/tags/releases/twisted-.2.0/twisted/internet/defer.py
        http://krondo.com/?page_id=1327
        http://blog.sina.com.cn/s/blog_704b6af70100py9n.html 
   

版权声明:本文为博主原创文章,未经博主允许不得转载。

 posted on 2014-03-03 17:21  Rex7  阅读(601)  评论(0编辑  收藏  举报