![](/img/trans.png)
[英]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.