如何结合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
吗?非得定义一个额外的函数不可?
4 个回答
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
,当你想传递参数时。如果你觉得这种“滥用”haskell风格的语法是“不错”的话。)
1
我想在myFunction完成任务后立刻停止反应器。
那么,创建一个包装器,先执行myFunction的工作,然后再停止反应器吗?
def wrapper(reactor, *args):
myFunction(*args)
reactor.stop()
reactor.callLater(0, wrapper, reactor, ...)
24
IReactorTime.callLater
和 Deferred
是通过 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()