【问题标题】:stop a twisted reactor after a gatherResults has finished在收集结果完成后停止扭曲反应器
【发布时间】:2013-11-17 22:58:54
【问题描述】:

twisted 的新手,只是尝试一些延迟的东西。我有以下代码组成了 100 个延迟调用的列表 - 每个都等待随机时间并返回一个值。该列表打印结果并最终终止反应器。

但是,我很确定我停止反应堆的方式可能......不太好。

__author__ = 'Charlie'

from twisted.internet import defer, reactor
import random

def getDummyData(x):
    """returns a deferred object that will have a value in some random seconds
    sets up a callLater on the reactor to trgger the callback of d"""
    d = defer.Deferred()
    pause = random.randint(1,10)
    reactor.callLater(pause, d.callback, (x, pause))
    return d


def printData(result):
    """prints whatever is passed to it"""
    print result


def main():
    """makes a collection of deffered calls and then fires them. Stops reactor at end"""
    deferred_calls = [getDummyData(r) for r in range(0,100)]
    d = defer.gatherResults(deferred_calls, consumeErrors = True)
    d.addCallback(printData)

    # this additional callback on d stops the reacor
    # it fires after all the delayed callbacks have printed their values
    # the lambda ignored: ractor.stop() is required as callback takes a function
    # that takes a parameter.
    d.addCallback(lambda ignored: reactor.stop())

    # start the reactor.
    reactor.run()

if __name__ == "__main__":
    main()

我假设通过添加回调:

d.addCallback(lambda ignored: reactor.stop())

对于收集的结果,实际上在所有延迟项目上添加了该回调?

如果是这样,那么可能有更优雅/正确的方法来做到这一点?

干杯!

【问题讨论】:

  • 这是一个很好的方法。
  • 旁注:_ 是被忽略变量的习惯用法。

标签: python twisted deferred


【解决方案1】:

我假设通过添加回调: d.addCallback(忽略 lambda:reactor.stop()) 收集到的结果实际上是在所有延迟项目上添加回调?

事实并非如此。 gatherResults 返回一个 Deferred。就像您可能遇到的任何其他 Deferred 一样。它的addCallback 方法和往常一样做同样的事情:添加一个函数,该函数将在一个回调链中的某一点被调用。

像这样一切都很好、规则和不特殊的原因是gatherResults 负责提供常规Deferred 所需的所有逻辑,它在所有输入Deferreds 有结果。

所以,请随意使用gatherResults,就像使用任何其他Deferred-returning API 一样。没什么特别的!

也就是说,从 Twisted 12.3 开始,有一个方便的实用程序可以用于此类事情 - twisted.internet.task.react。如果你使用 main 函数,它会是这样的:

def main(reactor):
    """makes a collection of deffered calls and then fires them. Stops reactor at end"""
    deferred_calls = [getDummyData(r) for r in range(0,100)]
    d = defer.gatherResults(deferred_calls, consumeErrors = True)
    d.addCallback(printData)
    return d

if __name__ == "__main__":
    from twisted.internet import task
    task.react(main, [])

请注意,您可以更改 getDummyData 使其不依赖于全局反应器:

def getDummyData(reactor, x):
    """returns a deferred object that will have a value in some random seconds
    sets up a callLater on the reactor to trgger the callback of d"""
    d = defer.Deferred()
    pause = random.randint(1,10)
    reactor.callLater(pause, d.callback, (x, pause))
    return d

def main(reactor):
    """makes a collection of deffered calls and then fires them. Stops reactor at end"""
    deferred_calls = [getDummyData(reactor, r) for r in range(0,100)]
    d = defer.gatherResults(deferred_calls, consumeErrors = True)
    d.addCallback(printData)
    return d

现在您的代码根本不需要任何 twisted.internet.reactor 导入。

您还可以在getDummyData 中使用twisted.internet.task.deferLater 来节省更多输入:

def getDummyData(reactor, x):
    """returns a deferred object that will have a value in some random seconds
    sets up a callLater on the reactor to trgger the callback of d"""
    pause = random.randint(1,10)
    return deferLater(reactor, pause, lambda: (x, pause))

【讨论】:

  • 哇 - 感谢您提供非常详细的答案。明天我会挖掘这个。
猜你喜欢
  • 1970-01-01
  • 2011-09-25
  • 2017-03-25
  • 1970-01-01
  • 2013-02-16
  • 2014-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多