Python';s`concurrent.futures`:根据完成顺序对futures进行迭代
我想要类似于Python';s`concurrent.futures`:根据完成顺序对futures进行迭代,python,multithreading,future,Python,Multithreading,Future,我想要类似于executor.map的东西,除了在迭代结果时,我想根据完成顺序对结果进行迭代,例如,首先完成的工作项应该首先出现在迭代中,这样迭代将阻止序列中的每个工作项尚未完成 我知道如何使用队列实现这一点,但我想知道是否可以使用futures框架 (我主要使用基于线程的执行器,所以我希望得到一个适用于这些执行器的答案,但也欢迎给出一个通用答案。) 更新:感谢您的回答!你能解释一下我是如何在executor.map中使用的吗executor.map是我使用futures时最有用、最简洁的工具,
executor.map
的东西,除了在迭代结果时,我想根据完成顺序对结果进行迭代,例如,首先完成的工作项应该首先出现在迭代中,这样迭代将阻止序列中的每个工作项尚未完成
我知道如何使用队列实现这一点,但我想知道是否可以使用futures
框架
(我主要使用基于线程的执行器,所以我希望得到一个适用于这些执行器的答案,但也欢迎给出一个通用答案。)
更新:感谢您的回答!你能解释一下我是如何在
executor.map
中使用的吗executor.map是我使用futures时最有用、最简洁的工具,我不愿意手动开始使用Future
对象。并发futures根据完成时间返回一个迭代器——这听起来正是您要找的
请让我知道,如果你有任何困惑或困难wrt的实施。亲切的问候,-David
返回一个迭代器
未来的实例(可能由不同的执行者创建)
实例)由fs给出,在完成(完成)时产生期货
或被取消)。之前完成的任何期货,如_completed()
被称为“将首先屈服”。返回的迭代器引发
如果调用了下一步(),但结果不可用,则TimeoutError
从原始调用as_completed()到超时秒后。
超时可以是int或float。如果未指定超时或无超时,
等待时间没有限制
您需要了解executor.map()
和executor.submit()
之间的区别。第一种方法将函数映射到参数向量。它非常类似于map
,但是异步启动任务<代码>提交(func,arg)
每次调用启动一个任务。在此任务中,func
应用于arg
下面是一个使用as_completed()
和submit()
的示例,我可以在python 3.0上运行它
from concurrent import futures
import urllib.request
URLS = ['http://www.foxnews.com/',
'http://www.cnn.com/',
'http://europe.wsj.com/',
'http://www.bbc.co.uk/',
'http://some-made-up-domain.com/']
def load_url(url, timeout):
return urllib.request.urlopen(url, timeout=timeout).read()
def main():
with futures.ThreadPoolExecutor(max_workers=5) as executor:
future_to_url = dict(
(executor.submit(load_url, url, 60), url)
for url in URLS)
for future in futures.as_completed(future_to_url):
url = future_to_url[future]
try:
print('%r page is %d bytes' % (
url, len(future.result())))
except Exception as e:
print('%r generated an exception: %s' % (
url, e))
if __name__ == '__main__':
main()
此处不使用map()
,任务通过submit
和as_completed()运行
返回fs给定的未来实例的迭代器,该迭代器生成
期货完成时(完成或取消)
,与内置函数一样,只按iterable的顺序返回结果,因此很遗憾,您无法使用它来确定完成顺序。这就是您想要的-以下是一个示例:
import time
import concurrent.futures
times = [3, 1, 2]
def sleeper(secs):
time.sleep(secs)
print('I slept for {} seconds'.format(secs))
return secs
# returns in the order given
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
print(list(executor.map(sleeper, times)))
# I slept for 1 seconds
# I slept for 2 seconds
# I slept for 3 seconds
# [3, 1, 2]
# returns in the order completed
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
futs = [executor.submit(sleeper, secs) for secs in times]
print([fut.result() for fut in concurrent.futures.as_completed(futs)])
# I slept for 1 seconds
# I slept for 2 seconds
# I slept for 3 seconds
# [1, 2, 3]
当然,如果需要使用映射接口,您可以创建自己的map\u as\u completed()
函数来封装上述内容(可能将其添加到子类Executor()
),但我认为通过Executor.submit()
创建未来实例是一种更简单、更干净的方法(还允许您不提供args、kwargs)
import time
import concurrent.futures
times = [3, 1, 2]
def sleeper(secs):
time.sleep(secs)
print('I slept for {} seconds'.format(secs))
return secs
# returns in the order given
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
print(list(executor.map(sleeper, times)))
# I slept for 1 seconds
# I slept for 2 seconds
# I slept for 3 seconds
# [3, 1, 2]
# returns in the order completed
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
futs = [executor.submit(sleeper, secs) for secs in times]
print([fut.result() for fut in concurrent.futures.as_completed(futs)])
# I slept for 1 seconds
# I slept for 2 seconds
# I slept for 3 seconds
# [1, 2, 3]