我想让我的程序可插拔。我想使用setuptools的方式,使用鸡蛋。
我已经能够创建一个插件来为某些功能提供替代类,我可以使用它。
我想选择在运行时使用的类;我的核心模块或任何插件中的一个。我想使用pkg_resources查询这些类的方式:
for entrypoint in pkg_resources.iter_entry_points("myapp.myclasses"):
如何在核心中为我的类创建一个EntryPoint对象并注册它,以便iter_entry_points将以与我的.egg插件类相同的方式返回它?
答案 0 :(得分:11)
pkg_resources.iter_entry_points
列出任何鸡蛋中给定名称的任何入口点,包括您自己的包裹。因此,如果entry_points
中的setup.py
条目列出以下内容,和您运行setup.py develop
来生成元数据,则会包含您自己的入口点:
[myapp.myclasses]
classentry1 = myapp.mymodule:myclassname1
classentry2 = myapp.mymodule:myclassname2
Babel project就是这样做的;在setup.py
中,它列出了babel.checkers
和babel.extractors
的入口点,这些入口点分别由babel.messages.checkers:_find_checkers
和babel.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元数据。