Python 我怎么知道所有的未来都在龙卷风中解决?
我有一些解析应用程序,它基本上执行以下操作Python 我怎么知道所有的未来都在龙卷风中解决?,python,tornado,future,Python,Tornado,Future,我有一些解析应用程序,它基本上执行以下操作 将start() start()调用另一个函数,让我们调用它get\u input() get\u input()是一个协同程序,它通过网络获取一些数据,然后调度另一个协同程序,process\u input(),将其添加为第一步添加的start() get\u input()还检查某些条件,这些条件取决于所获取的数据,并且可能会使用调整后的参数进行自我调度 现在,在这个条件呈现False之后,我知道不会有任何新的输入项要处理 但是我怎么知道还没有
- 将
start()
调用另一个函数,让我们调用它start()
get\u input()
是一个协同程序,它通过网络获取一些数据,然后调度另一个协同程序,get\u input()
,将其添加为第一步添加的process\u input()
start()
还检查某些条件,这些条件取决于所获取的数据,并且可能会使用调整后的参数进行自我调度get\u input()
False
之后,我知道不会有任何新的输入项要处理但是我怎么知道还没有解决的
get\u input()
和process\u input()
的未来呢
我想这可以通过实现一种计数器来解决,每次调用process\u input()
时,计数器都会递增,解析后会递减但是如果有一系列不同的协同程序呢?我如何跟踪它们的状态,以便如果我停止IOLoop,任务在得到解决之前不会死亡 也许,应该有某种分级计数 编辑: 2@dano
好的,我现在明白了。。。我没有注意。您确实没有阻止,因为它自己的呼叫在此列表中
但是
产量
构造,不使用添加回调
,否则我们将失去“等待”概念我创建了一个空的
Future()
对象我用我的decorator修饰每个启用了
@coroutine
的方法,它增加“metafuture”中的计数器字段,并向它们的未来添加一个自定义完成的回调,这应该会减少它
当它达到零时,“元未来”通过调用set\u result(None)
还有一个IOLoop回调函数可以精确地生成该元未来:
@coroutine
def wait_for_complete(self):
yield self._input_data_collected
yield self._all_futures_resolved
self.complete()
因此,在那之后,我们知道没有任何未来是悬而未决的。这是一种类似于手动实现refcounting的困难方法,但它涵盖了添加任务的
IOLoop.add_callback()
方法,您可以编写方法,使它们在所有工作完成之前不会返回,而不是安排回调。然后您可以只调用IOLoop.run\u sync(start)
,在所有处理完成之前,调用不会返回:
from tornado import gen
from tornado.ioloop import IOLoop
@gen.coroutine
def start():
yield get_input()
@gen.coroutine
def get_input(*args, **kwargs):
data = yield fetch_data_over_net()
futs = [] # list of Future objects
futs.append(process_input(data))
if should_call_myself(data):
futs.append(get_input(newargs, newkwargs))
yield futs # This will wait for all Future objects in the list to complete.
@gen.coroutine
def process_input(data):
# do stuff
if __name__ == "__main__":
IOLoop.instance().run_sync(start)
我们利用了这样一个事实,即协同程序返回
未来,并且Tornado支持这样一个事实,即我们可以尽可能多地并发运行,而无需从获取输入(因此开始)返回在完成所有相关工作之前。在完成处理之后,是否始终要停止IOLoop?或者是在带外停止IOLoop的请求,而您希望它在实际停止之前等待工作完成?@dano,据我所知,如果我调用IOLoop.stop()
,而某些未来仍未解决,它们将不会被处理。所以我假设我应该手动跟踪所有处理完成的时刻,然后stop()
it这是真的IOLoop.stop()
不会等待未完成的工作完成。但是,您可以组织应用程序,使其在完成工作后自动退出。很难说你不能真正了解你的程序是如何构造的。我知道龙卷风的这个特性,我实际上在另一个地方使用它。但是,如果我使用了yield[futures]
,get\u input()
的执行会一直阻塞,直到它们完成为止,这会影响性能,因为我可以立即运行另一个get\u input()
,而无需等待进程输入()。这就是为什么我使用add_callback()
来安排时间processing@Ojomio除了在start()
内部调用一次,并在get\u input()
自身内部递归调用一次之外,如何触发get\u input()
?我在示例中介绍了递归调用,它没有被process\u input
阻止;它们并行运行。如果您在问题中添加一些示例代码,以准确显示您正在做的事情,这可能会有所帮助。。。我没有注意。你真的没有阻止,因为它自己的调用在这个列表中是yield fetch\u data\u over\u net()
一个阻止调用?@user1045085它不会阻止IO循环,因为它是我们yield
的一个协同程序,但它是“阻止”的,因为执行流将等待它完成,然后再转到下一行。