Watch at Ease看見世界,讀懂生活。

科技 · 實用指南

出現 attempted relative import with no known parent package?先證明執行上下文

前導點通常不是根本謎題。先記錄 Python 如何啟動檔案、檢查 __package__ 與 __spec__,再誠實選擇套件模組、安裝命令或獨立腳本中的一種入口契約。

原創示意圖,對照直接執行 Python 檔案與使用 python -m 執行套件模組時的套件中繼資料。
原創編輯示意圖:直接執行可能沒有父套件,而 -m 可提供套件身分。 Watch at Ease

先用完全相同的失敗命令執行,並在修改匯入前印出 __name__、__package__、__spec__、sys.argv、目前目錄與 sys.path[0]。檔案即使位於看似套件的目錄中,也可能仍以頂層 __main__ 執行。Python 文件說明,直接執行原始檔時 __main__.__spec__ 是 None,因此前導點沒有已記錄的父套件可依附。

持久修復不是「多試幾個點」。先決定程式碼應是套件模組、安裝後命令,還是獨立腳本。從包含頂層套件的目錄用 python -m package.module 啟動套件模組;用 [project.scripts] 暴露穩定命令;或把很薄的獨立啟動器放在套件外並絕對匯入應用程式碼。最後重複預期命令,記錄模組來源與套件中繼資料作為退出證明。

1. 擷取真實失敗啟動,而不是較乾淨的替代命令

先用完全相同的失敗命令執行,並在修改匯入前印出 __name__、__package__、__spec__、sys.argv、目前目錄與 sys.path[0]。檔案即使位於看似套件的目錄中,也可能仍以頂層 __main__ 執行。Python 文件說明,直接執行原始檔時 __main__.__spec__ 是 None,因此前導點沒有已記錄的父套件可依附。 直接執行原始檔時,__main__.__spec__ 是 None,即使該檔案本可被匯入。

持久修復不是「多試幾個點」。先決定程式碼應是套件模組、安裝後命令,還是獨立腳本。從包含頂層套件的目錄用 python -m package.module 啟動套件模組;用 [project.scripts] 暴露穩定命令;或把很薄的獨立啟動器放在套件外並絕對匯入應用程式碼。最後重複預期命令,記錄模組來源與套件中繼資料作為退出證明。 python -m 透過匯入系統定位模組並提供模組中繼資料。

2. 證明套件根目錄與模組全名

先用完全相同的失敗命令執行,並在修改匯入前印出 __name__、__package__、__spec__、sys.argv、目前目錄與 sys.path[0]。檔案即使位於看似套件的目錄中,也可能仍以頂層 __main__ 執行。Python 文件說明,直接執行原始檔時 __main__.__spec__ 是 None,因此前導點沒有已記錄的父套件可依附。 python -m 透過匯入系統定位模組並提供模組中繼資料。

持久修復不是「多試幾個點」。先決定程式碼應是套件模組、安裝後命令,還是獨立腳本。從包含頂層套件的目錄用 python -m package.module 啟動套件模組;用 [project.scripts] 暴露穩定命令;或把很薄的獨立啟動器放在套件外並絕對匯入應用程式碼。最後重複預期命令,記錄模組來源與套件中繼資料作為退出證明。 相對匯入依據目前模組的套件名稱解析,而不是肉眼看到的目錄距離。

3. 只選擇一種入口契約

先用完全相同的失敗命令執行,並在修改匯入前印出 __name__、__package__、__spec__、sys.argv、目前目錄與 sys.path[0]。檔案即使位於看似套件的目錄中,也可能仍以頂層 __main__ 執行。Python 文件說明,直接執行原始檔時 __main__.__spec__ 是 None,因此前導點沒有已記錄的父套件可依附。 相對匯入依據目前模組的套件名稱解析,而不是肉眼看到的目錄距離。

持久修復不是「多試幾個點」。先決定程式碼應是套件模組、安裝後命令,還是獨立腳本。從包含頂層套件的目錄用 python -m package.module 啟動套件模組;用 [project.scripts] 暴露穩定命令;或把很薄的獨立啟動器放在套件外並絕對匯入應用程式碼。最後重複預期命令,記錄模組來源與套件中繼資料作為退出證明。 只切換工作目錄不會把直接檔案執行變成套件執行。

4. 拒絕只會搬移事故的修復

先用完全相同的失敗命令執行,並在修改匯入前印出 __name__、__package__、__spec__、sys.argv、目前目錄與 sys.path[0]。檔案即使位於看似套件的目錄中,也可能仍以頂層 __main__ 執行。Python 文件說明,直接執行原始檔時 __main__.__spec__ 是 None,因此前導點沒有已記錄的父套件可依附。 只切換工作目錄不會把直接檔案執行變成套件執行。

持久修復不是「多試幾個點」。先決定程式碼應是套件模組、安裝後命令,還是獨立腳本。從包含頂層套件的目錄用 python -m package.module 啟動套件模組;用 [project.scripts] 暴露穩定命令;或把很薄的獨立啟動器放在套件外並絕對匯入應用程式碼。最後重複預期命令,記錄模組來源與套件中繼資料作為退出證明。 安裝後的專案腳本會呼叫可匯入的模組函式,避免把內部檔案當命令邊界。

5. 移除診斷前先定義退出證明

先用完全相同的失敗命令執行,並在修改匯入前印出 __name__、__package__、__spec__、sys.argv、目前目錄與 sys.path[0]。檔案即使位於看似套件的目錄中,也可能仍以頂層 __main__ 執行。Python 文件說明,直接執行原始檔時 __main__.__spec__ 是 None,因此前導點沒有已記錄的父套件可依附。 安裝後的專案腳本會呼叫可匯入的模組函式,避免把內部檔案當命令邊界。

持久修復不是「多試幾個點」。先決定程式碼應是套件模組、安裝後命令,還是獨立腳本。從包含頂層套件的目錄用 python -m package.module 啟動套件模組;用 [project.scripts] 暴露穩定命令;或把很薄的獨立啟動器放在套件外並絕對匯入應用程式碼。最後重複預期命令,記錄模組來源與套件中繼資料作為退出證明。 有效退出證明會重複真實啟動命令,並記錄預期套件中繼資料與匯入來源。

原創決策圖,用來選擇 Python 套件模組或獨立腳本入口並驗證結果。
原創編輯示意圖:先選定一種入口契約,再證明同一命令匯入預期模組。 Watch at Ease