How to combine callLater and addCallback?

旧巷老猫 提交于 2020-01-22 17:57:06

问题


This is so broken, I hope you are merciful with me:

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

myFunction returns a deferred.

I hope it is clear what I want to do:

  • as soon as the reactor is running, I want to call myFunction. That is why I am using 0 as the delay parameter. Is there no other way except callLater? It looks funny to pass it a delay of 0.
  • I want to stop the reactor as soon as myFunction has completed the task.

The problems that I have so far:

  • AttributeError: DelayedCall instance has no attribute 'addCallback'. Fair enough! How do I put a callback in the callback chain started by myFunction then?
  • exceptions.TypeError: stop() takes exactly 1 argument (2 given).

To solve the second problem I had to define a special function:

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

And change the code to:

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

(still not working because of the callLater problem, but stopReactor will work now)

Is there really no other way to call reactor.stop except by defining an extra function?


回答1:


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()



回答2:


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, ...)



回答3:


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.)




回答4:


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


来源:https://stackoverflow.com/questions/8174437/how-to-combine-calllater-and-addcallback

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!