Python 从终端运行脚本时发生ModuleNotFoundError

Python 从终端运行脚本时发生ModuleNotFoundError,python,python-3.x,pycharm,Python,Python 3.x,Pycharm,我有以下文件夹结构: app \uuuu init\uuuuu.py utils \uuuu init\uuuuu.py transform.py 产品 \uuuu init\uuuuu.py fish.py 在fish.py中,我正在导入transform,如下所示:导入utils.transform 当我从Pycharm运行fish.py时,它工作得非常好。但是,当我从终端运行fish.py时,我得到了错误ModuleNotFoundError:No module name'

我有以下文件夹结构:

  • app
    • \uuuu init\uuuuu.py
    • utils
      • \uuuu init\uuuuu.py
      • transform.py
    • 产品
      • \uuuu init\uuuuu.py
      • fish.py
在fish.py中,我正在导入
transform
,如下所示:
导入utils.transform

当我从Pycharm运行fish.py时,它工作得非常好。但是,当我从终端运行fish.py时,我得到了错误
ModuleNotFoundError:No module name'utils'

我在终端中使用的命令:来自app文件夹
python产品/fish.py

我已经研究了这里建议的解决方案:,将应用程序文件夹的路径添加到
sys.path
帮助中。但是,我想知道是否有其他方法可以让它工作,而不必在
fish.py
中添加两行代码。这是因为我在/products目录中有许多脚本,不想在每个脚本中添加两行代码

我查看了一些开源项目,看到了许多从并行文件夹导入模块而不向sys.path添加任何内容的示例,例如:


如何使它以同样的方式为我的项目工作?

您可能希望运行
python-m products.fish
。这与
python products/fish.py
之间的区别在于前者大致相当于在shell中执行
import products.fish
(但是将
\uuuuuuu name\uuuuuu
设置为
\uu main\uuuuu
),而后者并不知道它在包层次结构中的位置。

这扩展了@Mad Physicast的答案


首先,假设
app
本身是一个包(因为您向它添加了
\uu init\uuuuuuuuupy
),并且
utils
产品
是它的子包,那么您应该将导入更改为
导入app.utils.transform
,并从根目录运行Python(是
app
的父项)。此答案的其余部分假设您已经这样做了。(如果您不是有意创建
app
根包,请在评论中告诉我。)


问题在于,您正在运行
app.products.fish
,就像它是一个脚本一样,即通过将文件的完整路径提供给
python
命令:

python应用程序/products/fish.py
这使Python认为这个
fish.py
文件是一个独立的脚本,不属于任何包的一部分。正如文档中所定义的(请参阅
下),这意味着Python将在与脚本相同的目录中搜索模块,即
app/products/

如果脚本名称直接引用Python文件,则目录 包含该文件的文件将添加到
sys.path
的开头,并且 作为
\uuuu主模块执行

但是当然,
app
文件夹不在
app/products/
中,因此如果您尝试导入
app
或任何子包(例如
app.utils
),它将抛出错误

启动作为包一部分的脚本的正确方法是使用
-m
(模块)开关(),该开关将模块路径作为参数,并将该模块作为脚本执行(但将当前工作目录保留为模块搜索路径):

如果给定此选项,[…]当前目录 将被添加到系统路径的开头

因此,您应该使用以下方法启动您的程序:

python-m app.products.fish
现在,当
app.products.fish
尝试导入
app.utils.transform
模块时,它将在当前工作目录(其中包含
app/..
树)中搜索
app
,并成功



作为个人建议:不要将可运行脚本放在包内。使用包仅存储所有逻辑和功能(函数、类、常量等),并编写一个单独的脚本来运行应用程序,将其放在包外。这将使您避免此类问题(包括),还有一个优点,就是您可以为同一个包编写多个运行配置,只需为每个包编写一个单独的启动脚本。

通过查看settings@NicolòGasparini我想我在Pycharm中使用了VirtualEnv:在项目解释器中,我选择了/application/venv/bin/pyt亲爱的。我也在终端中使用相同的VirtualEnv…你能显示你的
\uuu init\uuuuu.py
文件在哪里吗?还可以显示你如何从命令行运行你的模块。我猜PyCharm在设置路径方面非常聪明。看看这个,它应该可以满足你的需要,但是从长远来看,如果你的utils文件夹增长了,你可能会想要确保它在路径中,这样您就不必进行相对导入。不过,您可能会遇到这样的情况:感谢Mad,我刚刚尝试运行了
python-m产品。fish
,它可以工作!