python - 如何使用 setuptools 注册多个 Pluggy 插件

标签 python plugins pluggy

问题

我可以使用load_setuptools_entrypoints在pluggy中成功注册单个插件,但我只能注册一个。如果两个不同的插件尝试自行注册,则最后注册的插件将是唯一运行的插件。

我认为这不是 Pluggy 的工作方式,而且我犯了一个配置错误,但我不知道该怎么做。我认为pluggy应该允许多个插件在调用该钩子(Hook)时注册并串行运行。

项目结构

.
├── pluggable
│   ├── pluggable.py
│   └── pyproject.toml
├── plugin_a
│   ├── a.py
│   └── pyproject.toml
└── plugin_b
    ├── b.py
    └── pyproject.toml

与:

# pluggable/pluggable.py
import pluggy

NAME = "pluggable"
impl = pluggy.HookimplMarker(NAME)


@pluggy.HookspecMarker(NAME)
def run_plugin():
    pass


def main():
    m = pluggy.PluginManager(NAME)
    m.load_setuptools_entrypoints(NAME)
    m.hook.run_plugin()


if __name__ == "__main__":
    main()

# pluggable/pyproject.toml
[project]
name = "pluggable"
version = "1.0.0"
dependencies = ["pluggy==1.3.0"]

plugin_a/a.py和plugin_b/b.py具有相同的内容:

# plugin_a/a.py
import pluggy

from pluggable import impl


@impl
def run_plugin():
    print(f"run from {__name__}")


if __name__ == "__main__":
    run_plugin()

plugin_a/pyproject.toml 和plugin_b/pyproject.toml 将各自的模块注册为插件:

# plugin_a/pyproject.toml
[project]
name = "plugin_a"
version = "1.0.0"
dependencies = ["pluggy==1.3.0", "pluggable"]

[project.entry-points.pluggable]
run_plugin = "a"

plugin_b/pyproject.toml 是相同的,除了 run_plugin = "b"

演示运行

$ python -m venv venv
...
$ venv/bin/pip install -e pluggable -e plugin_a 
...
Successfully installed pluggable-1.0.0 plugin-a-1.0.0
$ venv/bin/python pluggable/pluggable.py
run from a
$ venv/bin/pip install -e plugin_b
...
Successfully installed plugin-b-1.0.0
$ venv/bin/python pluggable/pluggable.py
run from b

预期结果

最后我想看到的是

run from b
run from a

进一步分析

阅读 load_setuptools_entrypoints代码很清楚发生了什么。一旦一个插件注册到一个名称,PluginManager.get_plugin(name) returns that value ,这样其他插件就不会以相同的名称注册。

但是我希望得到帮助来理解什么是使用pluggy配置插件系统的正确方法,以便两个不同的python包可以使用相同的规范和钩子(Hook)注册自己,这样pluggy将串行运行它们?

最佳答案

正如您所观察到的,可能只有一个具有特定名称的插件。使用入口点时,插件的名称就是入口点的名称。

据我了解the docs ,钩子(Hook)通过spec/impl名称和签名进行匹配,在此过程中插件名称并不重要(插件只是相关钩子(Hook)实现的命名集合)。

根据这两个,入口点名称应该与插件名称匹配(并且应该是唯一的);请参阅plugin setup.py example 。因此,pyproject.toml 入口点看起来类似于 a = "a"

(与上面的代码不相关的可能问题是,应该使用 add_hookspecs(), example 将规范添加到管理器中。鉴于您的代码在没有它的情况下也可以工作,它可能不是强制性的,但它允许管理器验证违反规范的实现,所有示例似乎都使用它。)

关于python - 如何使用 setuptools 注册多个 Pluggy 插件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77579324/

相关文章:

python - 停止 Python Multiprocessing BaseManager 'serve_forever' 服务器?

python - 为什么在这种特殊情况下使用生成器对象?

python - AWS Sagemaker Pipelines 在引入注册步骤后抛出 "No finished training job found associated with this estimator"

python - 为什么不在隐式 __getitem__ 调用中调用 __getattribute__?

javascript - 在不同浏览器下检测已安装的插件?

javascript - 在 z 轴(z 索引)中绕另一个元素旋转

eclipse - *以编程方式*监控 Eclipse 插件堆大小