How to combine callLater and addCallback?

倾然丶 夕夏残阳落幕 提交于 2019-12-04 02:18:36

IReactorTime.callLater and Deferred are mixed together by twisted.internet.task.deferLater.

from twisted.internet import reactor, task

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

I want to stop the reactor as soon as myFunction has completed the task.

So, create a wrapper that does myFunction's work and then stops the reactor?

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

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

You need to attach the callback to the deferred that myFunction returns, since callLater doesn't return a function. Something like this might work:

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

But this is not tested.

You need to write a new function (here the lambda _: reactor.stop()) because callbacks to a deferred always take the result up to then. If you find yourself wanting to use callbacks for their side-effects and you don't care about propagating values often, you could define a little helper function:

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

And then do:

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

(What would be really neat would be to define an __rshift__ (and in-place analogue) for the Deferred class so you could do: myFunction(parameter1) >> reactor.stop, for when you want to abandon the argument, or myFunction(parameter1) >>= someotherfunc for when you want to propagate the argument. If you think that abusing haskellish syntax is "neat", anyway.)

If You need to trigger callback with some action, just do it (possibly there's no need to return deferred, or smth). Just to clarify things (using purely 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!'
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!