科技 · 實用指南
Python 顯示「bootstrapping phase」?先證明 spawn 重新匯入了什麼
這個 RuntimeError 表示 child interpreter 重新匯入 entry module 時,import path 又啟動了 process。先記錄 start method 與 launcher,再移動完整呼叫鏈。

這個 RuntimeError 表示 child interpreter 重新匯入 entry module 時,import path 又啟動了 process。先記錄 start method 與 launcher,再移動完整呼叫鏈。
只有原 launcher 重新執行後僅建立一個 parent、預期 workers 各執行一次並乾淨結束,而且不依賴強制變更 process method,修復才算完成。
1. 固定失敗 launch path
保存第一個 RuntimeError 的完整 traceback,記錄 Python、OS、sys.executable、sys.argv、__name__、__file__、get_start_method() 與實際 launcher。
_check_not_importing_main 前最上層 application frame 會指出 child 匯入 entry module 時哪個 import 或呼叫又建立 process。
2. 分離 import 與 entry-point 工作
definition、constant 與 import-safe setup 可留在 module scope。把 Pool、Process、Manager、ProcessPoolExecutor 和會建 worker 的 library call 移入 main(),只在 __main__ guard 下呼叫。
若 entry module 在 import 時已呼叫 helper,將 guard 放在 helper 內太晚;worker target 則應保留可匯入、可 pickle。
3. 實測 start method
Windows 使用 spawn,現代 macOS 預設 spawn;Python 3.14 起 POSIX 預設在支援處改為 forkserver。環境升級可能揭露 fork 曾掩蓋的遞迴 import。
不要強制 fork 來隱藏錯誤。需要明確方法時用 get_context,並在 application boundary 記錄,不要在 imported module 深處更改 global method。
4. 分支處理 frozen app 與第三方 pool
一般 interpreter 可省略 freeze_support;PyInstaller 因 child 重啟同一 executable 而覆寫它。通常在 guarded entry 呼叫,只有 import 更早啟動 multiprocessing 或 GUI 時才前移。
若 traceback 進入 library,確認 n_jobs、workers 或 processes 是否建 pool。單 worker 只適合診斷,恢復 parallelism 後 entry 仍須安全匯入。
5. 同 launcher 驗收
終止舊 process tree,再用相同 launcher 與 environment 全新啟動。確認 guard 僅在 parent、worker target 僅在 children 執行,且結束無 orphan。
將 traceback、launcher、start method、offending call chain、code movement 與 fresh result 保存成同一 audit record;source 與 packaged form 都要測。
