当列表中的任何未来完成时返回

2024-06-26 00:23:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个可以同时执行几个任务的协同程序:

@gen.coroutine
def scrape_trackers(self):
    yield [self.scrape_tracker(tracker) for tracker in self.torrent.trackers]

有些跟踪器永远不会响应(或者可能在一个小时内响应),所以我的代码永远无法通过这个方法,因为Tornado正在等待所有的全部完成。我如何只等待一个完成,然后在后台继续尝试其他的呢?在

比如:

^{pr2}$

我在考虑用IOLoop.add_callback()调用每个方法,并在它们完成时执行一些操作,但我不完全确定从那里开始应该做什么:

for tracker in self.torrent.trackers:
    future = self.scrape_tracker(tracker)
    IOLoop.add_future(future, self.tracker_scraped)

感谢任何帮助。在


Tags: 方法inselfaddfordeffuturetorrent
2条回答

yieldpoints库有一个WaitAny函数。不过,它早于龙卷风使用Futures,所以现在使用它有点麻烦。最好查看yieldpoints.WaitAny和{}的源代码,以将两者混合。在

或者,可以重新组织代码,使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]

我能想到的最好方法是返回一个新的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)

相关问题 更多 >