python / python/cpython

InterpreterPoolExecutor Failure When `__name__ == '__main__'`: Idiom Not Used

未關閉
#136,659 7 則留言 0 個 reaction 已指派 1 人 在 GitHub 檢視

@ericsnowcurrently 已經在處理了。

開始於 2025年7月14日。

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

描述

Bug report

Bug description:

From @corona10:

import concurrent.futures
from concurrent.futures import InterpreterPoolExecutor, ThreadPoolExecutor


def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

with InterpreterPoolExecutor(max_workers=5) as executor:
    futures = {executor.submit(fib, n): n for n in range(10)}
    for future in concurrent.futures.as_completed(futures):
        n = futures[future]
        data = future.result()
        print(f"fib({n}): {data}")

This fails with:

Exception: AttributeError: module '__main__' has no attribute 'fib'

The above exception was the direct cause of the following exception:

concurrent.interpreters.NotShareableError: object could not be unpickled

The above exception was the direct cause of the following exception:
...

The failure goes away if the "executable" part of the script is wrapped in an if __name__ == '__main__': block.

This is because of how Interpreter.call() sends functions between interpreters. It mostly pickles them. On the other side, functions are looked up by name in the defining module. For the __main__ module, this is a problem.

The original script only runs in the main interpreter, so the function will not be found in the other interpreter's __main__ module. We must run the script in the other interpreter, but without polluting __main__ and avoiding executing anything but the desired function definition. We partially solve this by calling runpy.run_path() with a different module name than __main__.

multiprocessing faces a similar situation. See the "Safe importing of main module" entry in the https://docs.python.org/3/library/multiprocessing.html#the-spawn-and-forkserver-start-methods section.

The solution here is probably the same: document that users should apply if __name__ == '__main__':. We may also be able to accommodate this in the code somewhat, since we know when we are running the script in the other interpreter. However, there's a limit to how much we can do so without introducing nontrivial complexity.

CPython versions tested on:

CPython main branch

Operating systems tested on:

No response

貢獻指南

開啟貢獻指南

從這裡開始

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

評估

這個 Issue 還沒有評估資料。

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

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