Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 当列表中的任何未来完成时返回_Python_Tornado_Coroutine - Fatal编程技术网

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
是未来应该返回值的方式,那么我看不出它怎么会比这里的更好。