pytest插件通过setuptools的entry_points机制注册,必须在pyproject.toml中配置[project.entry-points."pytest11"]或setup.py中指定entry_points={"pytest11": ["name = module:object"]},且module:object路径需可导入、函数名须严格匹配pytest预定义hook名(如pytest_configure)。

pytest插件怎么通过 entry_points 注册
entry_points 是 setuptools 提供的机制,让第三方包能“声明自己是个 pytest 插件”,而不是靠手动 import 或 conftest.py 硬塞。关键在于 setup.py 或 pyproject.toml 里写对 entry_points 配置项,否则 pytest 根本看不到你的插件。
常见错误是把 pytest11 写成 pytest、pytest_plugin 或漏掉 11(这是 pytest 的入口组名,和版本无关,固定叫 pytest11)。
- 用
pyproject.toml:必须在[project.entry-points."pytest11"]下定义键值对,键是插件名(任意合法标识符),值是module:object路径,比如myplugin = mypkg.plugin:pytest_configure - 用
setup.py:传入entry_points={"pytest11": ["myplugin = mypkg.plugin:pytest_configure"]} - 插件入口函数(如
pytest_configure)必须是可调用对象,且不能带参数(pytest 会自动传入config)
为什么 pytest --trace-config 找不到我的插件
这个命令只显示被成功加载的插件。如果没出现,说明注册失败或导入失败,不是“没生效”,而是根本没进 pytest 的插件发现流程。
典型原因包括:包没安装(或没用 -e 安装)、import 报错(比如模块里有语法错误、依赖缺失)、entry_points 指向的 module:object 路径不存在或不可访问。
立即学习“Python免费学习笔记(深入)”;
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
- 先运行
pip install -e .(确保本地开发包已以可编辑模式安装) - 手动试一下
python -c "from mypkg.plugin import pytest_configure",确认能 import - 检查
pip list输出里有没有你的包名;没有就说明安装失败 -
pytest --trace-config输出中若出现not found或failed to import,后面跟着的路径就是出问题的module:object
插件函数名必须是 pytest_ 开头吗
不是。只有你注册到 entry_points 的那个函数(比如 pytest_configure)需要是 pytest 预定义的 hook 名,其余内部函数随便起名。但 hook 名必须严格匹配,大小写、下划线都不能错。
比如你想改配置,就得用 pytest_configure;想拦截测试收集,就得用 pytest_collection_modifyitems。拼错一个字母,pytest 就当它不存在。
- 完整 hook 列表见 pytest 官方文档的
hook reference页面,别凭记忆写 - 自定义 hook(非 pytest 内置)不能靠
entry_points注册,得用pluggy手动注册,这属于高级用法,普通插件不需要 - 如果你在插件里定义了
pytest_addoption,但命令行参数没出现,大概率是函数名少了个s(应为pytest_addoption,不是pytest_addoption)
多个插件冲突时谁生效
pytest 按照插件加载顺序执行 hook,而加载顺序由 entry_points 注册顺序、安装顺序、以及是否内置决定。内置插件(如 pytest-cov)优先级高于第三方,同为第三方时,pip 安装顺序会影响 sys.path 排列,从而影响加载先后。
这不是 bug,是 pluggy 的设计:hook 调用是链式执行,每个 hook 函数可以修改参数、抛异常中断后续,也可以什么都不做。所以“谁生效”取决于具体 hook 的实现逻辑,而非简单覆盖。
- 调试时加
--debug,pytest 会在.pytestdebug里记录所有 hook 调用栈和返回值 - 避免在
pytest_runtest_makereport里直接 return,容易截断其他插件的报告逻辑 - 如果两个插件都改了同一配置项(比如
config.option.verbose),后加载的插件会覆盖前一个——除非前者用了config.addinivalue_line这类追加式操作
entry_points 看似只是配置一行字符串,但背后牵扯安装状态、导入路径、hook 命名规范、甚至 Python 的模块缓存机制。最常卡住人的地方,其实是 pip 安装没生效,却反复改代码——先确认 pip list 和 python -c "import xxx" 都 OK,再往下查。

















