在完成所有任务之前,关闭ThreadPoolExecutor

时间:2020-06-16 14:51:27

标签: python

我试图遍历一大串字符串(大约80,000),生成一个HTTP请求并处理响应,直到获得正确的字符串为止。我将列表和执行请求的函数传递给ThreadPoolExecutor.map()函数,然后遍历结果。

一旦从HTTP服务器收到正确的响应,我想取消所有剩余的期货并关闭脚本。为了简化编程,我希望不必自己跟踪每个未来。

我尝试使用shutdown(),但是无论是否指定等待,脚本都不会在所有排队的期货都完成之前结束。因此,如果列表中的字符串2000是正确的值,我仍然必须等待下一个78,000个期货完成,这可能会花费大量时间。

是否可以告诉ThreadPoolExecutor其余任务是不必要的,甚至不需要启动它们?

3 个答案:

答案 0 :(得分:1)

如果您可以切换到Python 3.9,则可以使用此功能built-in to the shutdown method

如果cancel_futures为True,则此方法将取消执行者尚未开始运行的所有未决期货。不论cancel_futures的值如何,所有已完成或正在运行的期货都不会被取消。

答案 1 :(得分:1)

您可以cancel()个期货。我看到您在问题中表示您不希望追踪期货,但这可能是您的最佳选择,而且看起来并不难:

from concurrent.futures import ThreadPoolExecutor, as_completed
import time

def process(duration):
    print(f"processing with duration {duration}")
    time.sleep(duration)
    if duration == 3:
        return "result found"

with ThreadPoolExecutor(max_workers=5) as executor:
    futures = [executor.submit(process, i) for i in range(80000)]
    for future in as_completed(futures):
        if future.result() == "result found":
            executor.shutdown(wait=False)
            print("shutdown")
            for f in futures:
                if not f.done():
                    f.cancel()
            break
print("about to exit")

答案 2 :(得分:0)

您可以使用Event对象来控制 transform 函数的执行。

import concurrent.futures
import threading

evt = threading.Event()
def transform(arg):
  if evt.is_set():
    return None

  ...
  return ret

with concurrent.futures.ThreadPoolExecutor() as pool:
  for result in pool.map(transform, data):
    if result == ...:
      evt.set()
      break