2011-11-17 133 views
10

之所以如此壞了,我希望你是仁慈的我:如何結合callLater和addCallback?

reactor.callLater(0, myFunction, parameter1).addCallback(reactor.stop) 
reactor.run() 

myFunction返回推遲。

我希望這是清楚我想做的事:

  • 只要反應堆在運行,我想打電話給myFunction。這就是爲什麼我使用0作爲延遲參數。除了callLater之外,沒有其他方法嗎?它看起來很有趣,通過它延遲0.
  • 我想盡快停止反應堆myFunction已完成任務。

是我到目前爲止的問題是:

  • AttributeError: DelayedCall instance has no attribute 'addCallback'。很公平!我如何在由myFunction開始的回調鏈中設置回調?
  • exceptions.TypeError: stop() takes exactly 1 argument (2 given)

要解決的第二個問題,我不得不定義一個特殊的功能:

def stopReactor(result): 
    gd.log.info('Result: %s' % result) 
    gd.log.info('Stopping reactor immediatelly') 
    reactor.stop() 

和代碼更改爲:

reactor.callLater(0, myFunction, parameter1).addCallback(stopReactor) 
reactor.run() 

(仍然沒有工作,因爲使用callLater問題的,但stopReactor現在會工作)

是否真的沒有其他方式可以撥打reactor.stop除了de罰款一個額外的功能?

回答

19

IReactorTime.callLaterDeferred通過twisted.internet.task.deferLater混合在一起。

from twisted.internet import reactor, task 

d = task.deferLater(reactor, 0, myFunction, parameter1) 
d.addCallback(lambda _: reactor.stop()) 
reactor.run() 
+0

我發現這個選項非常可讀的。 'lambda忽略'位對我來說很神奇:你能澄清一下它到底做了什麼嗎? – dangonfast

+4

Deferred上的回調函數用參數調用。 'reactor.stop'不帶任何參數。 '忽略lambda:reactor.stop()'接受和參數,忽略它,並且不帶任何參數地調用'reactor.stop'。 –

+3

這會更傳統一點:'lambda _:reactor.stop' – DonGar

1

我想在myFunction完成任務後立即停止反應堆。

因此,創建一個包裝,做myFunction的工作,然後停止反應?

def wrapper(reactor, *args): 
    myFunction(*args) 
    reactor.stop() 

reactor.callLater(0, wrapper, reactor, ...) 
0

您需要將回調附加到myFunction返回的延遲,因爲callLater不返回函數。像這樣的東西可能會工作:

reactor.callLater(0, lambda: myFunction(parameter1).addCallback(lambda _: reactor.stop()) 

但是,這沒有測試。

您需要編寫一個新函數(這裏是lambda _:reactor.stop()),因爲對延遲的回調總是取得結果。如果你發現自己想用他們的副作用回調和你不關心經常傳播的價值觀,你可以定義一個小助手功能:

def ignoringarg(f): 
    return lambda _: f() 

然後執行:

reactor.callLater(0, lambda: myFunction(paramater1).addCallback(ignoringarg(reactor.stop))) 

(真正整齊的是爲Deferred類定義一個__rshift__(和就地模擬),所以你可以這樣做:myFunction(parameter1) >> reactor.stop,當你想放棄參數時,或者myFunction(parameter1) >>= someotherfunc當你想傳播參數。如果您認爲濫用haskellish語法是「整潔的」,無論如何。)

0

如果您需要觸發回調了一些行動,只是做了(可能沒有必要返回延期,或不便)。 只是爲了澄清事情(使用純deferreds):

from twisted.internet import reactor, defer 

# That will be our deferred to play with 
# it has callback and errback methods 
d = defer.Deferred() 

def my_function(x): 
    print 'function', x 
    # need to trigger deferred upon function run? 
    # Lets tell it to do so: 
    d.callback(x) 

# That's our callback to run after triggering `d`  
def d_callback(y): 
    print 'callback ', y 

# now let's bind that callback to be actually launched by `d` 
d.addCallback(d_callback) 

# now adding another callback just to stop reactor 
# note lambda simply helps to agree number of arguments 
d.addCallback(lambda data: reactor.stop()) 

# so we'll call `my_function` in 2 secs, then it runs 
# then it triggers `d` to fire its callbacks 
# then `d` actually detonates the whole chain of its added callbacks 

reactor.callLater(2, my_function, 'asdf') # 'asdf' is some stupid param 

# Here how it works 
print 'Lets start!' 
reactor.run() 
print 'Done!'