pytest 的 PATH 问题‘ImportError: 没有名为...的模块’
- 2024-12-12 08:40:00
- admin 原创
- 90
问题描述:
我使用easy_install在 Mac 上安装了pytest,并开始为项目编写测试,其文件结构如下:
repo/
|--app.py
|--settings.py
|--models.py
|--tests/
|--test_app.py
py.test
在repo目录中运行,一切都会按照您预期的方式运行。
但是,当我在 Linux 或 Windows 上尝试执行相同的操作时(两者都安装了 pytest 2.2.3),只要它第一次从我的应用程序路径导入某些内容,它就会发出警报。例如,from app import some_def_in_app
。
我是否需要编辑我的PATH才能在这些系统上运行py.test ?
解决方案 1:
推荐方法pytest>=7
:使用pythonpath
设置
最近,pytest
添加了一个新的核心插件,支持sys.path
通过pythonpath
配置值进行修改。因此,解决方案现在变得更加简单,不再需要任何变通方法:
pyproject.toml
例子:
[tool.pytest.ini_options]
pythonpath = [
"."
]
pytest.ini
例子:
[pytest]
pythonpath = .
路径条目是相对于 rootdir 计算的,因此在这种情况下.
会添加repo
目录sys.path
。
还允许多个路径条目:对于布局
repo/
├── src/
| └── lib.py
├── app.py
└── tests
├── test_app.py
└── test_lib.py
配置
[tool.pytest.ini_options]
pythonpath = [
".", "src",
]
或者
[pytest]
pythonpath = . src
将添加app
和lib
模块到sys.path
,因此
import app
import lib
都可以。
原始答案(不推荐用于最近的 pytest 版本;仅用于pytest<7
):conftest
解决方案
侵入性最小的解决方案是conftest.py
在repo/
目录中添加一个名为的空文件:
$ touch repo/conftest.py
就是这样。无需编写自定义代码来破坏sys.path
或记住拖动PYTHONPATH
,或将__init__.py
其放入不属于的目录中(不过,python -m pytest
按照Apteryx的答案中的建议使用是一个很好的解决方案!)。
之后的项目目录:
repo
├── conftest.py
├── app.py
├── settings.py
├── models.py
└── tests
└── test_app.py
解释
pytest
在测试集合中查找conftest
模块来收集自定义钩子和装置,并且为了从它们导入自定义对象,pytest
将其父目录添加conftest.py
到sys.path
(在本例中为repo
目录)。
其他项目结构
如果您有其他项目结构,请将 放在conftest.py
包根目录(包含包但本身不是包,因此不包含)__init__.py
,例如:
repo
├── conftest.py
├── spam
│ ├── __init__.py
│ ├── bacon.py
│ └── egg.py
├── eggs
│ ├── __init__.py
│ └── sausage.py
└── tests
├── test_bacon.py
└── test_egg.py
src
布局
虽然这种方法可以与布局一起使用src
(放置conftest.py
在目录中src
):
repo
├── src
│ ├── conftest.py
│ ├── spam
│ │ ├── __init__.py
│ │ ├── bacon.py
│ │ └── egg.py
│ └── eggs
│ ├── __init__.py
│ └── sausage.py
└── tests
├── test_bacon.py
└── test_egg.py
请注意,添加src
会PYTHONPATH
削弱布局的意义和好处src
!您最终会测试存储库中的代码,而不是已安装的软件包。如果您需要这样做,也许您src
根本不需要目录。
下一步该怎么做
当然,conftest
模块不仅仅是一些帮助源代码发现的文件;它是框架的所有项目特定增强功能pytest
和测试套件定制发生的地方。在其文档pytest
中散布着大量有关conftest
模块的信息;从以下开始:本地每个目录插件conftest.py
此外,SO 有一个关于conftest
模块的很好的问题:在 py.test 中,conftest.py 文件有什么用?
解决方案 2:
我不确定为什么 py.test 没有在 PYTHONPATH 本身中添加当前目录,但这里有一个解决方法(从存储库的根目录执行):
python -m pytest tests/
它之所以有效是因为 Python 在 PYTHONPATH 中为您添加了当前目录。
解决方案 3:
我也遇到了同样的问题。我通过在目录__init__.py
中添加一个空文件解决了这个问题tests
。
解决方案 4:
cd
是的,如果你进入测试目录,源文件夹就不在 Python 的路径中。
您有两个选择:
手动将路径添加到测试文件。如下所示:
import sys, os
myPath = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, myPath + '/../')
使用环境变量运行测试
PYTHONPATH=../
。
解决方案 5:
pytest
以模块形式
运行:python -m pytest tests
例如,当项目层次结构为package/src package/tests并且在测试中从src导入时,就会发生这种情况。作为模块执行将把导入视为绝对的,而不是相对于执行位置的。
解决方案 6:
您可以在项目根目录中使用 PYTHONPATH 运行
PYTHONPATH=. py.test
或者使用 pip install 作为可编辑导入
pip install -e . # install package using setup.py in editable mode
解决方案 7:
我在 Flask 中遇到了同样的问题。
当我添加:
__init__.py
到测试文件夹,问题就消失了:)
应用程序可能无法将文件夹测试识别为模块。
解决方案 8:
我创建这个是为了回答你的问题和我自己的困惑。希望它能有所帮助。注意 py.test 命令行和 tox.ini 中的 PYTHONPATH。
https://github.com/jeffmacdonald/pytest_test
具体来说:您必须告诉 py.test 和 tox 在哪里找到您要包含的模块。
使用 py.test 您可以执行以下操作:
PYTHONPATH=. py.test
使用 tox,将其添加到您的 tox.ini 中:
[testenv]
deps= -r{toxinidir}/requirements.txt
commands=py.test
setenv =
PYTHONPATH = {toxinidir}
解决方案 9:
__init__.py
我通过删除源的父文件夹中的顶层来修复此问题。
解决方案 10:
ConftestImportFailure: ImportError('No module named ...
当我意外地将__init__.py
文件添加到我的 src 目录(它不应该是一个 Python 包,而只是一个所有源的容器)时,我开始收到奇怪的错误。
解决方案 11:
遗憾的是,这是 Python 中的一个问题...但在我看来,只需添加这个环境变量就是最舒服的方式:
export PYTHONPATH=$PYTHONPATH:.
您可以将此行放入.zshrc或.bashrc文件中。
解决方案 12:
我在学习 Flask 教程时遇到了同样的问题,并在官方 Pytest 文档中找到了答案。这与我(我想还有很多其他人)习惯做事的方式有点不同。
您必须setup.py
在项目的根目录中创建一个文件,其中至少包含以下两行:
from setuptools import setup, find_packages
setup(name="PACKAGENAME", packages=find_packages())
其中 PACKAGENAME 是你的应用程序的名称。然后你必须使用 pip 安装它:
pip install -e .
该-e
标志告诉pip以可编辑或“开发”模式安装软件包。因此下次运行时,pytest
它应该会在标准中找到您的应用程序PYTHONPATH
。
解决方案 13:
我之所以出现此错误,是因为我错误地使用了相对导入。在 OP 示例中,test_app.py 应使用例如导入函数
from repo.app import *
然而,__init__.py 文件大量地分散在文件结构中,这是行不通的,并且会产生 ImportError 错误,除非这些文件和测试文件位于同一目录中。
from app import *
下面是我在我的一个项目中所做的事情的一个例子:
这是我的项目结构:
microbit/
microbit/activity_indicator/activity_indicator.py
microbit/tests/test_activity_indicator.py
为了能够从 test_activity_indicator.py 访问 activity_indicator.py 我需要:
使用正确的相对导入启动 test_activity_indicatory.py:
from microbit.activity_indicator.activity_indicator import *
将 __init__.py 文件放入整个项目结构中:
microbit/
microbit/__init__.py
microbit/activity_indicator/__init__.py
microbit/activity_indicator/activity_indicator.py
microbit/tests/__init__.py
microbit/tests/test_activity_indicator.py
解决方案 14:
我遇到了类似的问题。pytest
无法识别在我工作环境中安装的模块。
我也通过安装pytest
到同一个环境中解决了这个问题。
解决方案 15:
此外,如果您pytest
在虚拟环境中运行,请确保pytest
模块已安装在虚拟环境中。激活虚拟环境并运行pip install pytest
。
解决方案 16:
对我来说,问题是tests.py
由 Django 和tests
目录一起产生的。删除tests.py
解决了这个问题。
解决方案 17:
根据Dirk Avery 在 Medium 上发表的一篇文章(并得到我的个人经验的支持),如果您在项目中使用虚拟环境,那么您不能使用系统范围的 pytest 安装;您必须在虚拟环境中安装它并使用该安装。
具体来说,如果您在两个地方都安装了它,那么简单地运行pytest
命令将不起作用,因为它将使用系统安装。正如其他答案所描述的那样,一个简单的解决方案是运行python -m pytest
而不是pytest
;这有效,因为它使用环境版本的 pytest。或者,您可以卸载系统版本的 pytest;重新激活虚拟环境后,该pytest
命令应该可以工作。
解决方案 18:
我遇到此错误的原因甚至更简单(您甚至可以说微不足道)。我没有安装模块pytest
。所以一个简单的操作apt install python-pytest
就帮我解决了。
'pytest' 将在 setup.py 中列为测试依赖项。请确保您也安装了测试要求。
解决方案 19:
由于没有人建议这样做,您也可以将路径传递给pytest.ini
文件中的测试:
[pytest]
...
testpaths = repo/tests
查看文档:https ://docs.pytest.org/en/6.2.x/customize.html#pytest-ini
Visual Studio Code的副作用:它应该在 UI 中选取单元测试。
解决方案 20:
我的设置
venv
在 vs-code 中有一个设置。vs-code 指向正确的可执行文件。
甚至
pytest.ini
设置为:
[pytest]
pythonpath = .
尝试导出
PYTHONPATH
但在虚拟环境中却无法工作。我的树看起来像:
root
venv
__init__.py
actions
actions.py
__init__.py
tests
test_actions.py
pytest.ini
我在
test_actions.py
做:
from actions.actions import ActionFetch
但正在
No action module found exception
虚拟环境也很活跃。
解决方案:我使用以下方法简单运行了测试:
pytest tests --import-mode=append
请参阅https://docs.pytest.org/en/7.1.x/explanation/pythonpath.html#:~:text=%2D%2Dimport%2Dmode%3Dappend
解决方案 21:
我们通过添加以下环境变量解决了该问题。
PYTHONPATH=${PYTHONPATH}:${PWD}/src:${PWD}/test
解决方案 22:
我的解决方案:
conftest.py
在目录中创建test
包含以下内容的文件:
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + "/relative/path/to/code/")
这会将感兴趣的文件夹添加到 Python 解释器路径,而无需修改每个测试文件、设置环境变量或弄乱绝对/相对路径。
解决方案 23:
正如Luiz Lezcano Arialdi指出的那样,正确的解决方案是将您的包安装为可编辑包。
由于我正在使用Pipenv,我考虑在他的回答中逐步添加如何使用 Pipenv 将当前路径安装为可食用路径,从而无需任何修改代码或丢失文件即可运行 pytest。
您将需要具有以下最小文件夹结构(文档):
package/
package/
__init__.py
module.py
tests/
module_test.py
setup.py
setup.py主要包含以下最少代码(文档):
import setuptools
setuptools.setup(name='package', # Change to your package name
packages=setuptools.find_packages())
然后您只需运行pipenv install --dev -e .
,Pipenv 就会将当前路径安装为可编辑包(--dev 标志是可选的)(文档)。
现在您应该可以pytest
顺利运行了。
解决方案 24:
如果这个 pytest 错误不是针对您自己的包出现的,而是针对您包的 requirements.txt 中 Git 安装的包出现的,则解决方案是切换到可编辑安装模式。
例如,假设您的包的 requirements.txt 有以下行:
git+https://github.com/foo/bar.git
您可以使用以下内容替换它:
-e git+https://github.com/foo/bar.git#egg=bar
解决方案 25:
如果什么都不起作用,请确保您的 test_module.py 列在正确的 src 目录下。有时它不会ModuleNotFoundError
因为模块放错位置或export PYTHONPATH="${PWD}:${PYTHONPATH}"
不起作用而给出,而是因为 test_module.py 被放置在 tests 文件夹下的错误目录中。
它应该是一对一的映射关系,递归的,而不是根文件夹应该命名为“tests”,包含测试代码的文件的名称应该以“test_”开头,例如,
./nlu_service/models/transformers.py
./测试/模型/test_transformers.py
这是我的经历。
解决方案 26:
如果您尝试通过 VSCode 的测试运行器运行,除了通过您选择的方法设置 PYTHONPATH 环境之外,还可以尝试settings.json
:
{
"python.testing.cwd": "${workspaceFolder}",
// or an appropriate path to your cwd
}
解决方案 27:
最近,我遇到了一种情况,由于导入错误,src(被测目标代码)中的本地导入会失败。
我们都知道文件根本就找不到。所以我的策略是将包含源的文件夹放在夹具中的sys.path中。
我的文件夹结构如下:
main_folder
--- target_file.py
--- utils.py
--- sub_utils.py
--- tests
--- test_target.py
--- conftest.py
当我运行测试时,我的 target_file 中的导入(它们看起来像 from utils.py import some_function) 。此外,utils.py从sub_utils.py导入函数。总之,一片混乱。
对我有用的是:
在我的conftest.py中,我使用了如下的装置:
@pytest.fixture(scope="module")
def import_target_file():
from pathlib import Path
import sys
sys.path.append(str(Path(__file__).parent.parent))
get_target_file = importlib.import_module("main_folder.target_file")
yield get_target_file
我的测试文件是什么样的:
class TestGetAppointments:
def test_valid_event(self, import_target_file):
"""Test to verify correct response when valid event is provided."""
test_event = {
"pathParameters": {
"start": "1",
"end": "1",
}
}
response = import_target_file.some_function(test_event)
解决方案 28:
测试经常因为无法导入模块而中断。
经过研究,我发现系统在错误的位置查看文件,我们可以通过将包含模块的文件复制到所述同一文件夹中来轻松解决问题,以便正确导入。
另一个解决方案建议是更改导入的声明并向 MutPy 显示单元的正确路径。但是,由于多个单元可能具有这种依赖关系,这意味着我们也需要在它们的声明中提交更改,因此我们更愿意将单元移动到文件夹中。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理必备:盘点2024年13款好用的项目管理软件
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)