Python 在测试完成后停止扭曲反应器

Python 在测试完成后停止扭曲反应器,python,twisted,deferred,Python,Twisted,Deferred,刚接触twisted,只是尝试一些延迟的东西。我有下面的代码,它组成了一个100个延迟调用的列表——每个调用随机等待一个时间并返回一个值。该列表打印结果并最终终止反应器 然而,我很确定我停止反应堆的方式可能是。。。不太好 __author__ = 'Charlie' from twisted.internet import defer, reactor import random def getDummyData(x): """returns a deferred object th

刚接触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())
在收集的结果中,是否实际添加了对所有延迟项的回调

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

干杯

我假设通过添加回调: d、 addCallback(lambda被忽略:reactor.stop()) 在收集的结果中,是否实际添加了对所有延迟项的回调

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

一切都是好的、规则的和非特殊的,原因是
gatherResults
考虑了所有必要的逻辑,只给出规则
Deferred
,即在所有输入
Deferred
都有结果之后返回结果

因此,可以像使用任何其他
延迟的
返回API一样随意使用
gatherResults
。这并不特别

这就是说,从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))

这是一个很好的方法。旁注:
\uu
是被忽略变量的惯用用法。哇-感谢您提供了非常详细的答案。我明天会把这个挖出来。