带有嵌套模块和测试的Python导入以及应用程序结构的最佳做法

时间:2018-11-06 05:19:16

标签: python python-3.x python-2.7 python-import pytest

摘要

我具有以下目录结构。我的目标是使module1可导入(在本例中为test_module1.py),当我在module1目录中时,也可以直接调用module1.py。我觉得这是一个很好的解决方案,或者我构建应用程序的方式出了问题,因此欢迎您提出建议的解决方案或对应用程序结构进行更改

详细信息

目录结构

.
├── module1
│   ├── __init__.py
│   ├── module1.py
│   ├── module2
│   │   ├── __init__.py
│   │   └── module2.py
└── tests
    └── test_module1.py

我的文件填充如下

test_module1.py

from module1.module1 import Module1
def test_fake():
    pass

module1.py

from module2.module2 import Module2
class Module1:
    pass #or regular __init__, etc

module2.py

class Module2:
    pass #or regular __init__, etc

所以我希望能够

1)从module1目录中运行module1

cd module1
python module1.py

2)使用

从主目录运行测试
pytest

在上述情况下,#1有效,但#2失败

    from module1.module1 import Module1
E   ModuleNotFoundError: No module named 'module1'

这是由于pytest仅在模块的测试目录中进行检查。通过运行python -m pytest可以解决该问题,它可以查看.目录

但是,仍然存在错误,这是我无法弄清的。

Traceback:
tests/test_module1.py:1: in <module>
    from module1.module1 import Module1
module1/module1.py:1: in <module>
    from module2.module2 import Module2
E   ModuleNotFoundError: No module named 'module2.Module2'

经过测试的解决方案

该测试找到module1,但是在导入module1时,它需要找到module2。它在.目录中查找,但不在./module1目录中查找。可以通过将module1.py中的导入从from module2.module2 import Module2更改为from .module2.module2 import Module2来解决(请注意在开头添加了.)。这是相对导入,绝对导入也可以解决此问题。两种解决方案都使python -m pytest通过,因此#2可以工作。但是,两者都破坏了功能#1,在这里我希望能够直接从模块内部运行module1。再往前走,我尝试从.运行module1.py,这给出了错误:No module named '__main__.module2'; '__main__' is not a package。我终于可以使用python -m module1.module1使其正常工作,但这似乎是超级环形交叉路口。下面是这些解决方案的更多信息

ModuleNotFoundError: What does it mean __main__ is not a package?

How to do relative imports in Python?

基本上,我发现绝对导入和相对导入现在强制必须使用-m从根目录中调用module1。这似乎向我表明了一个更大的问题,即在python中使用嵌套模块时,较低级别的模块将永远无法单独使用。假设module2包含两个文件,一个需要导入另一个。还将不得不使用相对或绝对导入,现在需要使用-m从module1运行module2,这使得构建这些脚本之一很麻烦。

我觉得我也可能会在__init__.py文件中做些事情,并在python文档https://docs.python.org/3/reference/import.html#submodules中发现了在__init__.py中进行相对导入的建议,但这并没有为我工作。

某些背景(可选阅读):我想要这个的原因是

1)我以崇高的文字进行开发,因此我可以在编写代码时直接直接构建文件

2)我花了大量时间研究根据模块和测试构建python应用程序的好方法,这就是我想出的。如果我做错了事,请告诉我,但是如果这是一个很好的结构,那么能够直接在模块中运行代码并能够(从测试脚本或其他地方)导入模块似乎是相当基本的功能,应该是可以实现的。

0 个答案:

没有答案