6

我想让我的程序可插入。我想使用 setuptools 这样做的方式,使用鸡蛋。

我已经能够制作一个插件来为某些功能提供替代类,并且我可以使用它。

我想选择在运行时使用的类;我的核心模块或任何插件中的一个。我想使用 pkg_resources 方式查询这些类:

for entrypoint in pkg_resources.iter_entry_points("myapp.myclasses"):

如何在核心中为我的类创建一个 EntryPoint 对象并注册它,以便 iter_entry_points 以与我的 .egg 插件类相同的方式返回它?

4

1 回答 1

11

pkg_resources.iter_entry_points列出任何egg中给定名称的任何入口点,包括您自己的包。因此,如果您的entry_points条目setup.py列出以下内容,并且您已经运行setup.py develop以生成元数据,那么您自己的入口点将被包括在内:

[myapp.myclasses]
classentry1 = myapp.mymodule:myclassname1
classentry2 = myapp.mymodule:myclassname2

Babel 项目正是这样做的。它setup.py列出了babel.checkers和的入口点,这些入口点分别由和babel.extractors查找。babel.messages.checkers:_find_checkersbabel.messages.extract:extract

如果您不想拥有一个setup.py文件(这很容易从模板创建和/或生成),那么您将不得不改变内部状态pkg_resources.working_set

  • working_set.entries是一个鸡蛋列表。您必须将项目顶级目录的路径添加到此目录。
  • working_set.entry_keys是从路径entries到包名称列表的映射。将您的项目添加为 `working_set.entry_keys[path] = ['package.name']
  • working_set.by_key是从包名到pkg_resources.Distribution实例的映射。您需要创建一个Distribution实例并将其存储在您的包名下:working_set.by_key['package.name'] = yourdistribution.

出于您的目的,该Distribution实例可能相当稀疏,但我至少会包含项目名称。不过,您需要有一个入口点地图:

yourdistribution = Distribution(project_name='package.name')
yourdistribution._ep_map = {'myapp.myclasses', {
    'classentry1': entrypointinstance_for_classentry1,
    'classentry2': entrypointinstance_for_classentry2,
}}

内部结构_ep_map通常根据需要从 egg-info 元数据中解析。

请注意,这完全依赖于可以在版本之间更改的未记录的内部数据结构。换句话说,你在这里是一个人。我会生成一个setup.py文件,然后运行python setup.py develop以生成 egg 元数据。

于 2012-11-24T20:47:09.830 回答