python / python/cpython

Cancel futures if concurrent.futures.Executor is used as a context manager and there is an exception?

未關閉
#130,975 2 則留言 3 個 reaction 已指派 1 人 在 GitHub 檢視

@gpshead 已經在處理了。

開始於 2026年6月13日。

stdlib type-feature
主要語言
Python
星號
77.2k
分支
36k
PR 合併指標
PR 指標待擷取

描述

I bumped into a bit of a rough edge related to how concurrent.futures.Executor instances behave when they're used as context managers and there is an exception raised from the with statement body.

I had some code like this (reduced to the bare minimum):

with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
    futures = {
        executor.submit(check_status, item): item
        for item in to_check
    }
    for index, future in enumerate(concurrent.futures.as_completed(futures)):
        print(f"{index}/{len(futures)} {future.result()}")

Now, as it happens check_status liked to raise an exception from time to time and this would be fine if the application stopped because of that but it kept going but in a weird way. What I saw was check_status kept producing logs but the print calls in the snippet above stopped being executed.

This is because of how Executor implements __exit__ – it waits for all pending futures to complete before propagating the exception:

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.shutdown(wait=True)
        return False

No in my case I started with thousands of futures so it could take hours for the process to finally crash.

Since Python 3.9 the shutdown method has the cancel_futures parameter (implemented in https://github.com/python/cpython/pull/18057): https://docs.python.org/3.9/library/concurrent.futures.html#concurrent.futures.Executor.shutdown.

I'm proposing changing the behavior of the context manager __exit__ to cancel futures if there is an exception:

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.shutdown(wait=True, cancel_futures=exc_val is not None)
        return False

This would allow the in-flight futures to finish but any further processing wouldn't happen and the exception would be reported in a (more) timely fashion.

cc @brianquinlan @pitrou as I saw you participate in the cancel_futures PR, if there's someone else I should ping here for visibility please let me know.

貢獻指南

開啟貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

評估

這個 Issue 還沒有評估資料。

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。