ModuleNotFoundError:没有名为' __ main __。xxxx&#39 ;; ' __主__'不是一个包

时间:2017-08-01 19:42:56

标签: python-3.x import module

目前正在尝试使用Python3并使用绝对导入将一个模块导入另一个模块但我收到错误ModuleNotFoundError: No module named '__main__.moduleB'; '__main__' is not a package。考虑一下这个项目结构:

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

moduleA.py3

from .moduleB import ModuleB
ModuleB.hello()

moduleB.py3

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

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

5 个答案:

答案 0 :(得分:27)

.moduleB是相对导入的。相对仅在首先导入或加载父模块时有效。这意味着您需要在当前运行时环境中的某处导入proj。当您使用命令python3 moduleA.py3时,它没有机会导入父模块。你可以:

  • from proj.moduleB import moduleB
  • 您可以创建另一个脚本,例如run.py,以调用from proj import moduleA

祝你旅途愉快地前往Python的绝佳之地。

答案 1 :(得分:10)

除了md-sabuj-sarker的答案,Python modules documentation中还有一个很好的例子。

这就是文档对intra-package-references的评价:

  

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

如果您运行python3 moduleA.py3,则moduleA被用作主要模块,因此使用绝对导入看起来是正确的选择。

但是,请注意,如果出于某种原因该软件包包含与该软件包同名的模块文件,则此绝对导入(from package.module import something)会失败(至少在我的Python 3.7中)。因此,例如,如果您拥有(使用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

或者,您可以按照建议的herehere删除.中的from .moduleB import,尽管我的PyCharm(2018.2.4)对此做了标记作为“未解决的参考”,并且无法自动完成。

答案 2 :(得分:4)

前言

我正在开发一个项目,该项目实际上是可以通过 pip 安装的Python程序包,但它也提供了命令行界面。使用pip install .安装项目后,我的项目运行没有问题,但是,在更改了其中一个项目文件中的内容后,每次由谁来执行此操作?我需要通过简单的python mypackage/main.py运行整个过程。

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

同一问题的不同面孔

我尝试从main.py模块中导入common.py中的一些函数。我尝试了会导致不同错误的不同配置,并希望与您分享我的观察结果,并为将来我留下简短的笔记。

相对导入

我首先尝试的是相对导入:

from .common import my_func

我使用以下简单的命令运行应用程序:python mypackage/main.py。不幸的是,这产生了以下错误:

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

此问题的原因是main.pypython命令直接执行,因此成为名为__main__的主模块。如果将这些信息与我们使用的相对导入相关联,则会得到错误消息__main__.common中的内容。 Python documentation中对此进行了解释:

  

请注意,相对导入基于当前模块的名称。由于主模块的名称始终为__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

答案 3 :(得分:0)

也许您可以在导入模块之前执行此操作:

moduleA.py3

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

from moduleB import ModuleB
ModuleB.hello()

将当前目录添加到环境目录

答案 4 :(得分:0)

只需将运行应用程序的文件重命名为 main.py

from app import app


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