Python 导入 - ModuleNotFoundError:没有名为 X 的模块

ber*_*olo 3 python module package python-3.x python-3.7

我可能已经阅读了这里所有关于进口的帖子,但我仍然无法弄清楚进口发生了什么,我花了几个小时试图让一个非常简单的例子工作,并且我真的在拉我的头发。

我正在使用 python 3.7 和 pycharm,但我正在从命令行运行我的代码,对于我使用 pytest 的单元测试。

我的项目结构是:

my_message_validator/
    __init__.py

    module_1/
        __init.py__
        foo.py

    module_2/
        __init.py__
        bar.py
        baz.py

    module_3
        context.py
        test_all.py
Run Code Online (Sandbox Code Playgroud)

模块_1。初始化.py

from module_1 import foo
Run Code Online (Sandbox Code Playgroud)

模块_2。初始化.py

# For some reason pycharm doesnt complain when I use '.' but if I use module_2 it does
from . import bar, baz
Run Code Online (Sandbox Code Playgroud)

如果我尝试从命令行运行我的代码或我的测试,无论我如何移动,我似乎都得到了ModuleNotFoundError: No module named,当我设法让测试工作时,我仍然无法从命令行单独运行我的代码。

如何导入module_1module_2并且这些居然包?我来自 java,发现导入更容易理解,我发现 python 导入非常混乱......

另外,我如何才能将我需要的任何内容导入到我的测试 module\package\folders 中context.py

目前测试上下文如下所示:

import os
import sys

# Is this needed as it doesnt seem to do anything?
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

from module_1.foo import Foo

from module_2 import bar, baz
Run Code Online (Sandbox Code Playgroud)

test_all.py我试图从这样的上下文文件中导入:

from .context import bar,baz
from .context import Foo

# Calling in test like
Foo.load_file(file)

bar.method_one()
baz.method_two()
Run Code Online (Sandbox Code Playgroud)

我是否需要所有__init.py__文件,我应该在其中放入什么以使我的方法和类公开\公开?我希望整个包都是可重用的,因此希望能够将它视为 java 中的 jar 文件。

任何帮助将不胜感激,因为似乎每次我更改某些内容时都会在不同的地方出现错误,python 现在似乎比 java 复杂得多。

Pie*_*rre 7

首先,不要使用相对导入(with .),因为它会导致多个问题。始终编​​写相对于项目根目录的导入。例如,您在from module_1.foo import Foo. 你也应该在test_all.pyand 中做到这一点context.py。此外,在使用相对导入后,您的__init__.py文件可以留空。

最有可能的是,Python 解释器找不到您的模块,因为PYTHONPATH环境变量不包含项目的根目录。如果您export PYTHONPATH="YOUR_PROJECT_ROOT_ABSOLUTE_PATH:$PYTHONPATH"在脚本之前运行,它应该按预期运行。为确保始终设置此变量,您可以将 export 语句添加到您的 shell 配置文件(例如.bashrc.bash_profile)。

和作者聊了聊,原来还有第四期。这是一个名称冲突,就像另一个问题中的那个。在他的项目目录中,module_1居然foo像它的孩子一样被调用foo.py,混淆了解释器。