簡體   English   中英

futures.wait() 或 futures.as_completed() 在所有期貨都已完成或取消時被阻止

[英]futures.wait() or futures.as_completed() blocked while all futures are Completed or Cancelled

我有一個關於 futures.as_completed() 或 futures.wait() 的錯誤,當所有 Futures 完成或取消時,它將被無限期地阻止。

這里重現的步驟:

在使用ThreadPoolExecutor.submit()提交期貨后,我正在等待使用futures.as_completed()futures.wait()的期貨。 在另一個線程中,我使用cancel_futures=True調用ThreadPoolExecutor.shutdown() ,然后在同一個過程中,我正在等待 Futures 超時完成。 等待將在延遲過去后返回,有 2 個列表:已完成的期貨和取消的期貨。 沒有更多的未決期貨。 但是,主線程中的第一個as_completed() (或wait() )仍然是阻塞的。

Python 文檔中,說明return_when=ALL_COMPLETED

當所有期貨完成或被取消時,function 將返回。

對於as_completed()

在完成時返回 [...] 期貨(已完成或取消的期貨)。

這符合我的情況。 這是一個錯誤還是我錯過了什么? 我試圖在同一個線程中調用shutdown() ,它沒有改變任何東西。


代碼示例:

import signal
import time
from concurrent import futures
from concurrent.futures import Future, ALL_COMPLETED
from concurrent.futures import ThreadPoolExecutor
from typing import Dict, Set


class SubThreads:
    def __init__(self):
        self.running_futures_url: Dict[str, Future] = {}
        self.webpage_crawler_th_pool = ThreadPoolExecutor(2)

    def shutdown(self):
        print("Waiting for lasts URL threads")
        self.webpage_crawler_th_pool.shutdown(wait=False, cancel_futures=True)
        finished_futures, still_running_futures = futures.wait(
            self.running_futures_url.values(), return_when=ALL_COMPLETED, timeout=5,
        )
        print("Shutdown done, remaining threads", len(still_running_futures))

    def crawl_url(self, url):
        print("Crawling webpage", url)
        time.sleep(3)
        print("Webpage crawled", url)
        return "URL Crawled"

    def run(self):
        urls = ['1', '2', '3', '4', '5']
        for url in urls:
            running_th = self.webpage_crawler_th_pool.submit(self.crawl_url, url)
            self.running_futures_url[url] = running_th

        print("Waiting for URLs to be crawled")
        # for _future in futures.as_completed(self.running_futures_url.values()):
        #     print("Future result:", _future.result())  # Will only return and print first 2 started (and completed) Futures
        finished_futures, still_running_futures = futures.wait(
            self.running_futures_url.values(), return_when=ALL_COMPLETED
        )
        print("SubThread finished (never called)", finished_futures, still_running_futures)


sub_thread = SubThreads()


def signal_handler(sig, frame):
    print("Signal caught, exiting ...", sig)
    sub_thread.shutdown()


signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
sub_thread.run()

我不會將shutdownwait=False一起使用。

請參閱文檔:

關機(等待=真)

停止接受新任務。 如果 wait 為 True,它會等待所有正在運行的任務完成。

因此,由於您通過wait=False ,您的as_completed將永遠等待,因為ThreadPoolExecutor將永遠不會停止運行,直到您使用wait=True調用shutdown

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM