为什么子模块的代码尝试直接或通过相对导入来导入同级子模块?

时间:2019-04-12 23:48:20

标签: python pytest

我正在编写一个可从命令行执行的脚本(通过向entry_points添加setup.py参数)。我的目录结构如下:

# Edit: package hasn't followed src packaging pattern, renamed to root_dir
root_dir/
    conftest.py
    setup.py
    module1/
        __init__.py
        script1.py
        script2.py
    module2/
        __init__.py
        other_script1.py
        other_script2.py
    tests/
        conftest.py
        some_tests/
            conftest.py
            test_some_parts.py
        some_other_tests/
            conftest.py
            test_these_other_parts.py

编辑:我的setup.py的entry_points参数如下:

    entry_points={
 'console_scripts': ['load_data = module1.script1:main']
},

目前,在script1.py的顶部,我有:

try:
    from script2 import func2
except ModuleNotFoundError:
    from .script2 import func2

当我安装软件包(pip install .)并通过命令行运行load_data时,它需要from script2 import func2。但是,当我运行测试时,它需要from .script2 import func2。我认为这很重要,但是我在src/目录(pytest tests/)中运行测试。

这个奇数try/except是一个创可贴,可让我运行测试并执行脚本。有没有更好的解决方案,或者至少有解释?

1 个答案:

答案 0 :(得分:3)

这是正确的:

from .script2 import func2

删除try / except hack。使用正确安装的程序包,pytest命令不应为解决导入目的而关心您所在的目录。请注意,pytest会将发现conftest.py文件的所有目录添加到sys.path中,这可能掩盖或加剧包装问题。

这是一个打包问题。您的src布局错误:setup.py应该在src根目录的外部处。 tests子目录应与src处于同一级别。重新阅读thisthis,然后重试(建议最好销毁/重新创建venv)。

对于使用src布局正确地流行的开源项目结构的几个示例,请检出attrscryptography

最后但并非最不重要的一点是,不要因弄错它而感到难过。 Python打包是一团糟,正确处理是非常棘手的。