繁体   English   中英

从终端运行脚本时出现 ModuleNotFoundError

[英]ModuleNotFoundError when running script from Terminal

我有以下文件夹结构:

  • app
    • __init__.py
    • utils
      • __init__.py
      • transform.py
    • products
      • __init__.py
      • fish.py

在 fish.py 中,我按如下方式导入transformimport 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 )并且utilsproducts是它的子包,你应该将导入更改为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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM