deferredのcancelソースコードからcancelの動作を分析する
まずは見てみましょう、Deferredの_init__メソッドのパラメータ:
def __init__(self, canceller=None):
ちょくせつぶんせき
366 def cancel(self):
367 """
368 Cancel this L{Deferred}.
369
370 If the L{Deferred} has not yet had its C{errback} or C{callback} method
371 invoked, call the canceller function provided to the constructor. If
372 that function does not invoke C{callback} or C{errback}, or if no
373 canceller function was provided, errback with L{CancelledError}.
374
375 If this L{Deferred} is waiting on another L{Deferred}, forward the
376 cancellation to the other L{Deferred}.
377 """
378 if not self.called:#deferdがアクティブになっていない場合は、cancelが次の操作を開始します.
379 canceller = self._canceller
380 if canceller:#Deferred関数でパラメータが指定されている場合
381 canceller(self)#はdeferred自体をパラメータとしてその関数に渡す
382 else:#Deferredインスタンスの生活中にパラメータが指定されていない場合
383 # Arrange to eat the callback that will eventually be fired
384 # since there was no real canceller.
385 self._suppressAlreadyCalled=1#この値を1に設定すると、後続のコールバックは「無視」されます.
386 if not self.called:#がアクティブになっていない場合は、cancellerで任意の結果またはエラーを使用してdeferredを励起することを選択できます(これにより、CancelledErrorよりも優先的に失敗します.
387 # There was no canceller, or the canceller didn't call
388 # callback or errback.
389 self.errback(failure.Failure(CancelledError())#はerrbackを呼び出します.cancellerが指定されている場合、deferredは1回しかアクティブにならないためdeferredがアクティブになります.callbackまたはerrbackが後にある場合、AlreadyCalledError異常が報告されます.
390 elif isinstance(self.result,Deferred):結果がdeferred(サブdeferred)の場合、サブdeferredはキャンセルされます.
391 # Waiting for another deferred -- cancel it instead.
392 self.result.cancel()
コードを参照:
出力:
I need to cancel this deferred:
errback got: [Failure instance: Traceback (failure with no frames)::
]
Traceback (most recent call last):
File "t.py", line 18, in
d.callback("ok")
File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 362, in callback
self._startRunCallbacks(result)
File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 451, in _startRunCallbacks
raise AlreadyCalledError
twisted.internet.defer.AlreadyCalledError
コードが次の場合:
キャンセル時にdeferredが完全にアクティブになっているため(戻り値がdeferredではない)、if not selfのためcancelは効果がない.calledもelif isinstance(self.result,Deferred)も条件を満たしていない.
出力は次のとおりです.
callback got: ok
コードが次の場合:
上のコードは、canceller関数でエラーコールバックをアクティブにし、cancelソースコードのself.errback(failure.Failure(CancelledError()))はself.calledはTrueです.
出力結果:
I need to cancel this deferred:
errback got: [Failure instance: Traceback (failure with no frames):: error
]
Traceback (most recent call last):
File "t.py", line 17, in
d.callback("ok")
File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 362, in callback
self._startRunCallbacks(result)
File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 451, in _startRunCallbacks
raise AlreadyCalledError
twisted.internet.defer.AlreadyCalledError
cancellerパラメータを指定しない場合、コードは次のとおりです.
出力結果:
errback got: [Failure instance: Traceback (failure with no frames)::
]
cancelの後のコールバックがキャンセルされたことがわかります.
def __init__(self, canceller=None):
ちょくせつぶんせき
366 def cancel(self):
367 """
368 Cancel this L{Deferred}.
369
370 If the L{Deferred} has not yet had its C{errback} or C{callback} method
371 invoked, call the canceller function provided to the constructor. If
372 that function does not invoke C{callback} or C{errback}, or if no
373 canceller function was provided, errback with L{CancelledError}.
374
375 If this L{Deferred} is waiting on another L{Deferred}, forward the
376 cancellation to the other L{Deferred}.
377 """
378 if not self.called:#deferdがアクティブになっていない場合は、cancelが次の操作を開始します.
379 canceller = self._canceller
380 if canceller:#Deferred関数でパラメータが指定されている場合
381 canceller(self)#はdeferred自体をパラメータとしてその関数に渡す
382 else:#Deferredインスタンスの生活中にパラメータが指定されていない場合
383 # Arrange to eat the callback that will eventually be fired
384 # since there was no real canceller.
385 self._suppressAlreadyCalled=1#この値を1に設定すると、後続のコールバックは「無視」されます.
386 if not self.called:#がアクティブになっていない場合は、cancellerで任意の結果またはエラーを使用してdeferredを励起することを選択できます(これにより、CancelledErrorよりも優先的に失敗します.
387 # There was no canceller, or the canceller didn't call
388 # callback or errback.
389 self.errback(failure.Failure(CancelledError())#はerrbackを呼び出します.cancellerが指定されている場合、deferredは1回しかアクティブにならないためdeferredがアクティブになります.callbackまたはerrbackが後にある場合、AlreadyCalledError異常が報告されます.
390 elif isinstance(self.result,Deferred):結果がdeferred(サブdeferred)の場合、サブdeferredはキャンセルされます.
391 # Waiting for another deferred -- cancel it instead.
392 self.result.cancel()
コードを参照:
from twisted.internet import defer
def canceller(d):
print "I need to cancel this deferred:",d
def callback(res):
print 'callback got:', res
def errback(err):
print 'errback got:', err
d = defer.Deferred(canceller)
d.addCallbacks(callback,errback)
d.cancel()
d.callback("ok") # def canceller,cancel errback, AlreadyCalledError
出力:
I need to cancel this deferred:
errback got: [Failure instance: Traceback (failure with no frames):
]
Traceback (most recent call last):
File "t.py", line 18, in
d.callback("ok")
File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 362, in callback
self._startRunCallbacks(result)
File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 451, in _startRunCallbacks
raise AlreadyCalledError
twisted.internet.defer.AlreadyCalledError
コードが次の場合:
from twisted.internet import defer
def canceller(d):
print "I need to cancel this deferred:",d
d.errback("error")
def callback(res):
print 'callback got:', res
def errback(err):
print 'errback got:', err
d = defer.Deferred(canceller)
d.addCallbacks(callback,errback)
d.callback("ok")
d.cancel()
キャンセル時にdeferredが完全にアクティブになっているため(戻り値がdeferredではない)、if not selfのためcancelは効果がない.calledもelif isinstance(self.result,Deferred)も条件を満たしていない.
出力は次のとおりです.
callback got: ok
コードが次の場合:
from twisted.internet import defer
def canceller(d):
print "I need to cancel this deferred:",d
d.errback("error")
def callback(res):
print 'callback got:', res
def errback(err):
print 'errback got:', err
d = defer.Deferred(canceller)
d.addCallbacks(callback,errback)
d.cancel()
d.callback("ok")
上のコードは、canceller関数でエラーコールバックをアクティブにし、cancelソースコードのself.errback(failure.Failure(CancelledError()))はself.calledはTrueです.
出力結果:
I need to cancel this deferred:
errback got: [Failure instance: Traceback (failure with no frames):
]
Traceback (most recent call last):
File "t.py", line 17, in
d.callback("ok")
File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 362, in callback
self._startRunCallbacks(result)
File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 451, in _startRunCallbacks
raise AlreadyCalledError
twisted.internet.defer.AlreadyCalledError
cancellerパラメータを指定しない場合、コードは次のとおりです.
from twisted.internet import defer
def canceller(d):
print "I need to cancel this deferred:",d
d.errback("error")
def callback(res):
print 'callback got:', res
def errback(err):
print 'errback got:', err
d = defer.Deferred()
d.addCallbacks(callback,errback)
d.cancel()
d.callback("ok")
出力結果:
errback got: [Failure instance: Traceback (failure with no frames):
]
cancelの後のコールバックがキャンセルされたことがわかります.