[英]ModuleNotFoundError when launching script from terminal but not in interpreter
[英]ModuleNotFoundError when running script from Terminal
我有以下文件夾結構:
app
__init__.py
utils
__init__.py
transform.py
products
__init__.py
fish.py
在 fish.py 中,我按如下方式導入transform
: import utils.transform
。
當我從 Pycharm 運行 fish.py 時,它運行得非常好。 但是,當我從終端運行 fish.py 時,出現錯誤ModuleNotFoundError: No module named 'utils'
。
我在終端中使用的命令:來自 app 文件夾python products/fish.py
。
我已經研究過這里建議的解決方案: 從不同文件夾導入文件,將應用程序文件夾的路徑添加到sys.path
幫助中。 但是我想知道是否有任何其他方法可以使其工作而無需在fish.py
添加兩行代碼。 是因為我/products目錄下有很多腳本,不想每一個都加兩行代碼。
我查看了一些開源項目,我看到了許多從並行文件夾導入模塊而不向 sys.path 添加任何內容的示例,例如: https : //github.com/jakubroztocil/httpie/blob/master/httpie/plugins /builtin.py#L5
如何讓它以同樣的方式適用於我的項目?
您可能想要運行python -m products.fish
。 它和python products/fish.py
的區別在於,前者大致相當於在 shell 中執行import products.fish
(但__name__
設置為__main__
),而后者不知道它在包層次結構中的位置.
這擴展了@Mad Physicist 的回答。
首先,假設app
本身是一個包(因為你向它添加了__init__.py
)並且utils
和products
是它的子包,你應該將導入更改為import app.utils.transform
,並從根目錄(其父目錄)運行 Python app
)。 本答案的其余部分假設您已完成此操作。 (如果您不打算將app
作為根包,請在評論中告訴我。)
問題是您正在運行app.products.fish
就好像它是一個腳本一樣, app.products.fish
文件的完整路徑提供給python
命令:
python app/products/fish.py
這使得 Python 認為這個fish.py
文件是一個獨立的腳本,不屬於任何包的一部分。 如文檔中所定義(參見此處,在<script>
),這意味着 Python 將在與腳本相同的目錄中搜索模塊,即app/products/
:
如果腳本名稱直接引用 Python 文件,則將包含該文件的目錄添加到
sys.path
的開頭,並且該文件作為__main__
模塊執行。
但當然, app
文件夾不在app/products/
,因此如果您嘗試導入app
或任何子包(例如app.utils
),它將引發錯誤。
啟動作為包一部分的腳本的正確方法是使用-m
(模塊)開關( 參考),它將模塊路徑作為參數並將該模塊作為腳本執行(但保持當前工作目錄為模塊搜索路徑):
如果給出此選項,[...] 當前目錄將被添加到
sys.path
的開頭。
因此,您應該使用以下內容來啟動您的程序:
python -m app.products.fish
現在,當app.products.fish
嘗試導入app.utils.transform
模塊時,它將在您當前的工作目錄(其中包含app/...
樹)中搜索app
並成功。
作為個人建議:不要將可運行的腳本放在包中。 僅使用包來存儲所有邏輯和功能(函數、類、常量等),並編寫一個單獨的腳本來根據需要運行您的應用程序,將其放在包之外。 這將使您免於此類問題(包括雙重導入陷阱),並且還有一個優勢,您可以通過為每個包編寫單獨的啟動腳本來為同一個包編寫多個運行配置。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.