Python 当列表中的任何未来完成时返回
我有一个协同程序,它应该同时执行一些任务:Python 当列表中的任何未来完成时返回,python,tornado,coroutine,Python,Tornado,Coroutine,我有一个协同程序,它应该同时执行一些任务: @gen.coroutine def scrape_trackers(self): yield [self.scrape_tracker(tracker) for tracker in self.torrent.trackers] 一些跟踪器将永远不会响应(或者可能在一小时内响应),所以我的代码永远不会通过这个方法,因为Tornado正在等待它们全部完成。我如何只等待一个任务完成,然后在后台继续尝试其他任务 比如: yield WhenAny
@gen.coroutine
def scrape_trackers(self):
yield [self.scrape_tracker(tracker) for tracker in self.torrent.trackers]
一些跟踪器将永远不会响应(或者可能在一小时内响应),所以我的代码永远不会通过这个方法,因为Tornado正在等待它们全部完成。我如何只等待一个任务完成,然后在后台继续尝试其他任务
比如:
yield WhenAnyComplete(map(self.scrape_tracker, self.torrent.trackers))
我正在考虑使用IOLoop.add_callback()
调用这些方法中的每一个,并在它们完成后执行一些操作,但我不完全确定从那里开始:
for tracker in self.torrent.trackers:
future = self.scrape_tracker(tracker)
IOLoop.add_future(future, self.tracker_scraped)
非常感谢您的帮助。我能想到的最好办法是返回一个新的
Future
,并让第一次成功的函数调用给出结果:
def scrape_trackers(self):
result = Future()
for tracker in self.torrent.trackers:
future = self.scrape_tracker(tracker)
future.add_done_callback(lambda f: self.tracker_done(f, result))
return result
def tracker_done(self, future, result_future):
if future.exception():
logging.warning('Tracker could not be scraped: %s', future.exception())
return
logging.info('Scraped tracker %s', future)
if self.unconnected_peers:
result_future.set_result(True)
该库具有WaitAny
功能。不过,它比Tornado使用期货的时间要早,所以现在使用起来有点麻烦。最好查看yieldpoints.WaitAny
和tornado.gen.yieldfourture
的源代码,将两者混合使用
或者,您可以重新组织代码,以便不再需要WaitAny
。与其在结果完成时剥离一个协同程序,不如为每个任务启动一个新的协同程序,并在结束时将它们全部加入:
@gen.coroutine
def process_tracker(self, tracker):
result = yield self.scrape_tracker(tracker)
# Do whatever you'd do after WaitAny here. All the process_tracker
# calls can proceed in parallel as their results are ready.
@gen.coroutine
def process_all_trackers(self, trackers):
yield [self.process_tracker(t) for t in trackers]
A?@minitech:听起来不错。Twisted、Tornado和Tulip似乎没有任何相似之处,所以如果我想不出什么东西,我会看看async。没关系,据我所知,它们有相同的问题。另一方面,from:corroutines可以通过引发特殊异常来“返回”。这行吗?@minitech:我可以从协同程序中返回,但我只想在第一次成功擦伤发生时才这样做。所有这些都应该同时进行,这是导致问题的原因。如果它们按顺序运行,我就可以这样做。如果
set\u result
是未来应该返回值的方式,那么我看不出它怎么会比这里的更好。