技術 · 實用指南
終端可執行,systemd 卻報 ModuleNotFoundError?先證明直譯器與 sys.path
重裝套件前,先記錄服務的直譯器、前綴、使用者、工作目錄與模組搜尋路徑;只修復一個已證明的邊界,再重跑同一探針。

只在 systemd 出現的 ModuleNotFoundError,先視為執行邊界差異。服務可能使用不同 Python、虛擬環境、使用者、主目錄、工作目錄或搜尋路徑。
不要先用 sudo pip、chmod、全域 PYTHONPATH 或互動式 activate。兩邊執行相同脫敏探針,再做一項可回復修改。
凍結失敗服務與成功終端
保存 unit 內容、關鍵屬性與 journal 回溯;秘密只記錄名稱與脫敏路徑。
在成功 shell 與服務身分下收集相同 id、pwd、Python、pip 與探針資料。
建立匯入邊界帳本
記錄 executable、prefix/base_prefix、cwd、uid/gid、HOME、sys.path 與 find_spec。
用該直譯器執行 python -m pip show;其他 pip 的清單不是匯入證據。
分類第一個差異
直譯器不同就讓 ExecStart 指向虛擬環境 Python;不需啟用腳本。
cwd 不同就設定絕對 WorkingDirectory 或正確封裝;路徑不同先找來源。
修復套件邊界而非症狀
使用可重建、服務帳號可讀的環境,並用目標 Python 的 -m pip。
Environment 只放非秘密設定;PYTHONPATH 僅作窄測試,不用 root 掩蓋問題。
重載並重跑探針
必要時 daemon-reload、重啟,再確認所有邊界與 module spec。
測一個真實工作;重啟後仍正確匯入且未擴權才關閉事件。
用失敗分支排除假修復
pip show 有而 find_spec 無時,查發行名/匯入名、選用元件與 editable 路徑。
200/CHDIR 先修目錄;ExecStart 找不到先修執行檔,兩者都早於匯入。
