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
版权声明:本文为博主原创文章,未经博主允许不得转载。