导入我的函数装饰器时出现 pytest 错误

pytest error when importing my function decorator

我正在为我的软件中的一个函数创建一个 pytest 单元测试。

甚至在开始测试之前,pyunit 似乎无法导入我的 "cache_offline" 装饰器,当我在我的测试中导入我正在测试的函数时,它是间接导入的。

我正在使用 Anaconda 嵌入 Python 3.7 和 pytest 5.2.2

我试图注释掉装饰器应用于我的函数的代码,当我这样做时,pytest 错误消失并且测试正确执行。

我的测试在 ./tests/scripts/test_scripts_helper.py 中,我 运行 pytest 在项目根目录下 . Pytest 正确找到了我的测试(请参阅错误消息),所以这不是手头的问题。

我的测试从包 vorace.scripts_helper 导入并想测试函数 read_tiff_tag,它从包 vorace.core.misc 导入函数 safe_mkdir,它导入包 vorace.core.vorace,其中3个函数用package vorace.core.misc

中的装饰器cache_offline装饰

我在项目的根目录下使用 py.testpython -m pytest 尝试了两个 运行 测试。

我的项目有以下结构(简化)。 代码根是 ./vorace 测试根是 ./tests

.
├── conftest.py
├── tests
│   ├── __init__.py
│   ├── scripts
│   │   ├── __init__.py
│   │   └── test_scripts_helper.py
│   └── tests_data
│       └── test_ROI.tif
└── vorace
    ├── __init__.py
    ├── core
    │   ├── __init__.py
    │   ├── misc.py
    │   └── vorace.py
    └── scripts
        ├── __init__.py
        ├── batch_analyzis.py
        └── scripts_helper.py

我试过了:

我怀疑存在某种循环导入问题,但我一直被告知它不会在 python 中发生。也许装饰器是这个规则的例外?

我的 vorace.core.misc 代码,带有装饰器

from vorace.core import vorace
[...]
def cache_offline(cache_path=os.getcwd()):
    [...]
    def decorator(func):
        [...]
        def wrapper(*args, **kwargs):
            [...]
            return result
        return wrapper
    return decorator

def safe_mkdir(path):
    [...]

vorace.core.vorace

中的修饰函数之一
from vorace.core.misc import *
[...]
@cache_offline(cache_path=".cache")
def classify_clusters_by_connectivity(xyz_data):
   [...]
[...]

在项目根

中执行py.test的输出
==================== test session starts ====================
platform linux -- Python 3.7.3, pytest-5.2.2, py-1.8.0, pluggy-0.12.0
rootdir: /home/flo/PycharmProjects/VorAce
plugins: arraydiff-0.3, openfiles-0.3.2, doctestplus-0.3.0, remotedata-0.3.1
collected 0 items / 1 errors                                                                                  

==================== ERRORS ====================
_________ ERROR collecting tests/scripts/test_scripts_helper.py _________
tests/scripts/test_scripts_helper.py:1: in <module>
    import vorace.scripts.scripts_helper as sh
vorace/scripts/scripts_helper.py:6: in <module>
    from vorace.core.misc import safe_mkdir
vorace/core/misc.py:8: in <module>
    from vorace.core import vorace
vorace/core/vorace.py:91: in <module>
    @cache_offline(cache_path=".cache")
E   NameError: name 'cache_offline' is not defined


如果我在 tests/scripts/test_scripts_helper.py 文件中执行一个简单的 0 == 0 测试而不从我的项目中导入,则测试 运行 会成功。

当您 运行 ./tests/scripts/test_scripts_helper.py python 自动将 ./tests/scripts/ 设置到 PYTHONPATH 但不设置任何其他目录时,因此您从其他自定义文件的所有导入都应该失败。

将所有工作目录设置到 PYTHONPATH 环境变量中。 Linux shell.

上的类似内容
PYTHONPATH="${PYTHONPATH}:$dir

编辑:我终于得到了循环导入的确认。 与我的想法相反,从模块中导入特定名称 like in from x import y 可以对循环导入敏感,而 import x 不能。

为了解决这个问题,我只是导入了模块并使用了使用模块前缀函数调用的语法。 更多信息:https://www.reddit.com/r/Python/comments/51hdup/from_import_vs_import_on_circular_import/

最终与装饰器或 pytest 无关的问题。


我通过将我的 cache_offline 装饰器放在一个单独的包 vorace.core.caching.py 中解决了这个问题。现在我只从需要修饰的函数所在的 vorace.core.vorace 导入这个包。

这样我的装饰器被人为排除在我的单元测试导入的代码之外,但仍然可供我的其余代码用于正常的应用程序执行。

不过pytest这里还是有问题,导入应该不会失败。我仍在接受任何可以解释为什么 pytest 无法导入我的装饰器的答案,并且我保留 resolve 以获得此类答案。