gpt4 book ai didi

python - python3中pytest的布局和导入

转载 作者:太空狗 更新时间:2023-10-29 21:54:03 29 4
gpt4 key购买 nike

我在从我的 pytest 函数导入模块时遇到问题。我知道这方面有一百万个问题,但我已经阅读了很多,但我仍然无法理解。

$ tree
.
└── code
├── eight_puzzle.py
├── missionaries_and_cannibals.py
├── node.py
├── search.py
└── test
├── test_eight_puzzle.py
└── test_search.py

2 directories, 6 files
$
$ grep import code/test/test_search.py
import sys
import pytest
import code.search
$
$ pytest
...
ImportError while importing test module '~/Documents/code/test/test_search.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
code/test/test_search.py:14: in <module>
import code.search
E ModuleNotFoundError: No module named 'code.search'; 'code' is not a package
...

我希望它能起作用。 “代码”是一个包,对吧? Python 3 中的包是其中包含 .py 文件的任何目录。

我也尝试过使用相对导入 - from .. import search - 我得到以下结果。

ImportError while importing test module '~/Documents/code/test/test_search.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
code/test/test_search.py:14: in <module>
from .. import search
E ImportError: attempted relative import with no known parent package

我还尝试修改 sys.path,如图所示 here ,指定我的 PYTHONPATH,并在代码和测试中添加 init.py 文件。

我可以在不使用 setuptools 的情况下使这个导入工作吗?这只是为了试验,所以我不想处理开销。

注意我正在使用 conda 可能也很重要,因为当我使用带有 init.py 文件的 python 2 pip 安装版本的 pytest 时它似乎可以工作。

最佳答案

关于没有__init__.py 文件的目录的一些注意事项:

隐式命名空间包

尽管没有 __init__.py 的目录是 Python 3 中的有效导入源,但它不是常规包,而是隐式命名空间包(有关详细信息,请参见 PEP 420)。在其他属性中,隐式命名空间包在导入时是二等公民,这意味着当 Python 在 sys.path 中有两个同名包时,一个是常规包,另一个是隐式命名空间包,无论第一个包是什么包,都会优先使用常规包。自己检查一下:

$ mkdir -p implicit_namespace/mypkg
$ echo -e "def spam():\n print('spam from implicit namespace package')" > implicit_namespace/mypkg/mymod.py
$ mkdir -p regular/mypkg
$ touch regular/mypkg/__init__.py
$ echo -e "def spam():\n print('spam from regular package')" > regular/mypkg/mymod.py
$ PYTHONPATH=implicit_namespace:regular python3 -c "from mypkg.mymod import spam; spam()"

这将打印 spam from regular package:尽管 implicit_namespacesys.path 中排在第一位,mypkg.mymod 而不是导入 regular 因为 regular/mypkg 是一个常规包。


现在你知道了,因为你的包 code 是一个隐式的命名空间包,Python 会更喜欢定期导入 code 如果它遇到你的。不幸的是,there is a module code in the stdlib ,所以这实际上是一个“反向名称隐藏”问题:您有一个与来自 stdlib 的对象同名的导入对象,但它没有隐藏 stdlib 导入,而是隐藏了您的导入。

因此,为了使布局可用,您需要做两件事:

  1. code 目录一个唯一的名字(对于这个答案的例子,让它成为 mycode)
  2. 之后,您仍然需要在从项目根目录运行测试时修复 sys.path,因为它本身不在 sys.path 中。你有一些可能性:
    • 将一个空的 conftest.py 文件添加到根目录(除了 mycode 目录)。这将指示 pytest 将根目录添加到 sys.path(有关解释,请参阅 here)。您现在可以像往常一样运行 pytest,导入将被解析;
    • 通过 python -m pytest 运行测试 - 调用解释器直接将当前目录添加到 sys.path;
    • 通过 PYTHONPATH 环境变量将当前目录添加到 sys.path,例如运行 PYTHONPATH=。 pytest.

关于python - python3中pytest的布局和导入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52808625/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com