如何组合callLater和addCallback?

时间:2011-11-17 21:17:22

标签: python twisted

这太破碎了,我希望你对我很仁慈:

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吗?

4 个答案:

答案 0 :(得分:21)

IReactorTime.callLaterDeferredtwisted.internet.task.deferLater混合在一起。

from twisted.internet import reactor, task

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

答案 1 :(得分:1)

  

我想在myFunction完成任务后立即停止反应堆。

那么,创建一个包装器来执行myFunction的工作,然后停止反应器?

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

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

答案 2 :(得分: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)))

(对于__rshift__类定义Deferred(和就地模拟)真的很简洁,所以你可以这样做:myFunction(parameter1) >> reactor.stop,当你想要的时候放弃参数,或者myFunction(parameter1) >>= someotherfunc当你想传播参数时。如果你认为滥用haskellish语法是“整洁的”,无论如何。)

答案 3 :(得分:0)

如果你需要通过某个动作触发回调,那就去做吧(可能不需要返回deferred或smth)。 只是为了澄清事情(使用纯粹的延期):

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!'