ModuleNotFoundError: 没有名为“__ main__. xxxx”的模块; “__ main__”不是包

当前正在尝试在 Python 3中工作,并使用绝对导入将一个模块导入到另一个模块中,但是我得到了错误 ModuleNotFoundError: No module named '__main__.moduleB'; '__main__' is not a package。考虑一下这个项目结构:

proj
__init__.py3 (empty)
moduleA.py3
moduleB.py3

模块 A.py3

from .moduleB import ModuleB
ModuleB.hello()

模块 B.py3

class ModuleB:
def hello():
print("hello world")

然后运行 python3 moduleA.py3会出现错误。这里需要更改什么?

114855 次浏览

.moduleB是相对重要的。只有当首先导入或加载父模块时,“相对”才能工作。这意味着你需要在当前执行期函式库的某个地方导入 ABc1。当您使用命令 python3 moduleA.py3时,它没有机会导入父模块。你可以:

  • 您可以创建另一个脚本(比如说 run.py)来调用 from proj import moduleA

祝你去巨蟒之地的旅程一路顺风。

除了 md-sabuj-sarker 的答案之外,在 Python 模块文档中还有一个非常好的例子。

医生是这样评价 包内引用的:

请注意,相对导入基于当前模块的名称。因为主模块的名称始终是 "__main__",所以用作 Python 应用程序主模块的模块必须始终使用绝对导入。

如果运行 python3 moduleA.py3moduleA将用作主模块,因此使用绝对导入看起来是正确的做法。

但是,如果由于某种原因,包中包含与包同名的模块文件(至少在我的 Python 3.7中是这样) ,那么请注意,这种绝对导入(from package.module import something)将失败。因此,例如,如果您(使用 OP 的例子) :

proj/
__init__.py (empty)
proj.py (same name as package)
moduleA.py
moduleB.py

在这种情况下,你会得到:

ModuleNotFoundError: No module named 'proj.moduleB'; 'proj' is not a package

或者,你也可以像建议的 给你给你那样移除 from .moduleB import中的 .,这似乎有效,尽管我的 PyCharm (2018.2.4)将其标记为“未解决的引用”并且无法自动完成。

也许您可以在导入模块之前这样做:

模块 A.py3

import os
import sys
sys.path.append(os.path.dirname(os.path.abspath(__file__)))


from moduleB import ModuleB
ModuleB.hello()

将工作目录添加到环境目录

前言

我正在开发一个项目,它实际上是一个可以通过 Pip安装的 Python 包,但是它也公开了一个命令行接口。在使用 pip install .安装我的项目之后,运行它没有问题,但是,嘿,谁会在每次更改项目文件中的某些内容之后都这样做呢?我需要通过简单的 python mypackage/main.py运行整个程序。

/my-project
- README.md
- setup.py
/mypackage
- __init__.py
- main.py
- common.py

同一个问题的不同面

我尝试从 common.py模块导入 main.py中的一些函数。我尝试了不同的配置,产生了不同的错误,我想与大家分享我的观察,并留下一个简短的笔记,以便将来我也。

相对重要性

我首先尝试的是一种相对重要的方法:

from .common import my_func

我使用简单的 python mypackage/main.py运行我的应用程序:

ModuleNotFoundError: No module named '__main__.common'; '__main__' is not a package

这个问题的原因是 main.py是由 python命令直接执行的,因此成为名为 __main__的主模块。如果我们将这些信息与我们使用的相对导入连接起来,我们将得到错误消息中的内容: __main__.common。这在 Python 文档中有解释:

请注意,相对导入基于当前模块的名称。因为主模块的名称始终是 __main__,所以用作 Python 应用程序主模块的模块必须始终使用绝对导入。

当我用 pip install .安装软件包并运行它时,它运行得非常好。我还能够在 Python 控制台中导入 mypackage.main模块。看起来只有直接运行才有问题。

绝对重要

让我们按照文档中的建议,将 import 语句更改为不同的内容:

from common import my_func

如果我们现在试着像以前一样运行这个程序: python mypackage/main.py,那么它就会像预期的那样工作!但是,当您像我一样,在使用 Pip安装命令行工具之后,开发一些需要作为独立命令行工具使用的工具时,需要注意一点。我用 pip install .安装了我的软件包,然后尝试运行它..。

ModuleNotFoundError: No module named 'common'

更糟糕的是,当我打开一个 Python 控制台,并试图手动导入 main模块(import mypackage.main)时,我得到了与上面相同的错误。原因很简单: common不再是一个相对导入,因此 Python 尝试在已安装的包中找到它。我们没有这样的一揽子计划,这就是为什么它失败了。

具有绝对导入的解决方案只有在创建一个使用 python命令执行的典型 Python 应用程序时才能很好地工作。

使用包名导入

还有第三种导入 common模块的可能性:

from mypackage.common import my_func

这与 相对重要性方法没有很大的不同,只要我们从 mypackage的上下文来做。同样,尝试用 python mypackage/main.py运行这个程序的结果也是相似的:

ModuleNotFoundError: No module named 'mypackage'

多么令人恼火啊,解释器是对的,你没有安装这样的软件包。

解决办法

对于简单的 Python 应用程序

只要使用绝对导入(不带点) ,一切都会好起来的。

用于开发中的可安装 Python 应用程序

使用相对导入,或者在开头使用包名称进行导入,因为在安装应用程序时需要这样做。在开发中运行这样的模块时,可以使用 -m选项执行 Python:

-m mod : run library module as a script (terminates option list)

因此,不要使用 python mypackage/main.py,而是这样做: python -m mypackage.main

只需将运行应用程序的文件重命名为 Main Py:

from app import app




if __name__ == '__main__':
app.run()

import os

import sys

sys.path.append(os.path.dirname(os.path.abspath(__file__)))

将解决进口路径问题。