如何将 executor.map() 放入循环中并将每次迭代分开?

How to put executor.map() in a loop and separate each iteration?

我想向 10,000 台主机发送 HTTP 请求,并且我有 5 个不同的 header 值。我想发送附有第一个 header 值的 10,000 个请求,等待它完成,然后开始附有第二个 header 值的第二个 10,000 个请求,在每个 10,000 个请求中我想使用多线程来加快进程。

要使用多线程向 10,000 台主机发送请求,我可以使用以下代码:

with concurrent.futures.ThreadPoolExecutor(max_workers = CONNECTIONS) as executor:
  args = ((url, header) for url in urls)
  executor.map(lambda p: send_request(*p), args) 

为了实现我最终想要的,我正在考虑以这种方式包装上面的代码:

for header in headers:
  with concurrent.futures.ThreadPoolExecutor(max_workers = CONNECTIONS) as executor:
    args = ((url, header) for url in urls)
    executor.map(lambda p: send_request(*p), args) 

不过好像不行。它运行循环但似乎跳过了整个循环 body。我想知道我哪里做错了,正确的做法是什么。

您不是在捕捉地图的未来 return 并等待结果。这是您需要的同步点,以便 "all of header 1 finished before 2"

有多种方法可以做到这一点,例如使用 as_completed,但在您的情况下,您需要做的只是为结果设置虚拟 evaluate/wait:

for header in headers:
  with concurrent.futures.ThreadPoolExecutor(max_workers = CONNECTIONS) as executor:
    args = ((url, header) for url in urls)
    futures = executor.map(lambda p: send_request(*p), args)
    list(futures)

在这种情况下,list 将遍历 futures 生成器,等待它们全部求值,创建一个等待同步点,然后继续