跳转到主要内容

基于setuptools入口点机制的插件管理器

项目描述

https://github.com/aiidateam/reentry/workflows/ci/badge.svg https://codecov.io/gh/aiidateam/reentry/branch/develop/graph/badge.svg

Reentry

一个基于setuptools入口点的插件管理器,速度提高了10倍

存档通知

Python 3.8将importlib.metadata引入到Python标准库。使用import importlib.metadata和使用entry_points()函数扫描入口点都非常快。

单独的importlib-metadata软件包将此功能回传到python >=3.6,并且从版本4.6.3(或更早版本)开始,扫描甚至比标准库还要快。

以下是在MacBook Air M1(2020)上,在python 3.9.1 conda环境中(安装了248个软件包,其中约30个注册了入口点)记录的时间。

pkg_resources:总时间约147毫秒

$ python -mtimeit -n1 -r1 'import pkg_resources'
1 loop, best of 1: 146 msec per loop
$ python -mtimeit -s 'import pkg_resources as pkg' 'pkg.iter_entry_points("aiida.calculations")'
500000 loops, best of 5: 435 nsec per loop

importlib.metadata:总时间约39毫秒

$ python -mtimeit -n1 -r1 'import importlib.metadata'
1 loop, best of 1: 17.8 msec per loop
$ python -mtimeit -s 'import importlib.metadata as im' 'im.entry_points()'
50 loops, best of 5: 21.4 msec per loop

importlib-metadata软件包(v4.6.3):总时间约40毫秒

$ python -mtimeit -n1 -r1 'import importlib_metadata'
1 loop, best of 1: 33.8 msec per loop
$ python -mtimeit -s 'import importlib_metadata as im' 'im.entry_points()'
50 loops, best of 5: 5.94 msec per loop

reentry(v1.3.1):总时间约25毫秒

$ python -mtimeit -n1 -r1 'import reentry'
1 loop, best of 1: 23.8 msec per loop
$ python -mtimeit  -s 'from reentry.default_manager import PluginManager as p' 'p().get_entry_map()'
200 loops, best of 5: 1.07 msec per loop

随着更快(固态)硬盘和更快importlib实现的到来,reentry带来的速度优势已经大幅减少(在上述基准测试中下降到约15毫秒或40%)。虽然可能仍然存在一些边缘情况,其中reentry是有用的,但我们将停止使用它,因此将存档此存储库。

有兴趣继续维护reentry的用户,请在问题跟踪器上创建一个问题。

特性

  • 查找插件:reentry在文件中保持入口点的映射

  • 速度:reentry提供了一个EntryPoint实现,它通过牺牲搜索和加载速度来换取额外的检查

  • 自动注册:在您的setup.py中使用reentry_register: True来自动注册插件

请注意,reentry_register会在reentry上创建一个构建时依赖关系。建议的解决方法是使用PEP518中描述的方法,pip 10已添加对它的支持:在setup.py旁边放置一个包含以下内容的文件pyproject.toml

[build-system]
# Minimum requirements for the build system to execute.
requires = ["setuptools", "wheel", "reentry"]

指定构建依赖关系的另一种方法是在您的setup.py中放置以下内容

setup(
   ...
   setup_requires=[reentry],
   ...
)

此替代方案与所有版本的pip兼容,但在与旧SSL库链接的系统中(例如,某些版本的OS X的系统Python)会失败。

限制

  • 支持具有额外依赖项的入口点(name = module_name:attrs [extras])。但是,尝试加载它们会导致导入pkg_resources并放弃速度提升。

快速入门

在您的插件setup.py中使用以下内容

setup(
   ...
   setup_requires=['reentry'],
   reentry_register=True,
   entry_points={
      'my_plugins': ['this_plugin = this_package.subpackage:member'],
      ...
   }

然后从宿主包中迭代已安装的插件

from reentry import manager
available_plugins = manager.iter_entry_points(group='my_plugins')
for plugin in available_plugins:
   plugin_object = plugin.load()
   plugin_object.use()

该语法与setuptools的pkg_resources保持一致,因此您可以用作后备

try:
   from reentry import manager as entry_pt_manager
except:
   import pkg_resources as entry_pt_manager

entry_pt_manager.iter_entry_points(...)
...

Reentry配置

Reentry支持从配置文件获取信息。该文件将在以下路径中搜索

  • <HOME>/.reentryrc

  • <HOME>/.config/reentry/config

配置文件具有ini格式,并支持以下键

[general]
datadir=/path/to/data/dir
data_filename=name

datadir是reentry存储包含已注册入口点信息的数据文件的文件夹。如果配置文件不存在于上述路径之一,则将datadir设置为<HOME>/.config/reentry/data。如果想要自己选择名称,而不是让reentry选择,则可以使用data_filename。警告:默认情况下,reentry为每个Python解释器创建一个独立的数据文件,以避免在不同Python环境中混合入口点。在配置文件中设置data_filename告诉reentry始终使用此数据文件,如果同时在多个Python环境中使用reentry,可能会导致意外的行为。

您还可以通过环境变量设置reentry的配置选项

  • datadir可以通过REENTRY_DATADIR定义。

  • data_filename可以通过REENTRY_DATA_FILENAME定义。

环境变量优先于配置文件。

用途?

为了在时间敏感的情况下(如命令行界面)使入口点对插件可用!

Setup工具的入口点系统便于用于基于插件的Python应用程序。它允许独立的Python包作为宿主包(或彼此)的插件,从而使宿主程序易于查找和迭代插件的相关数据结构。

然而,导入setuptools所需的时间与已安装的分布数量成比例增长,在中等复杂的环境中,它可能达到0.5秒。查找和加载插件可能是时间敏感的,例如在需要加载子命令的命令行工具中,100毫秒的延迟是明显的。

导入setuptools的pkg_resources需要时间,因为它验证环境中所有分布的依赖项是否正确安装。这允许入口点具有额外的依赖项或“额外内容”(entry_point = module_name:attrs [extras])。

Reentry省略了“额外内容”入口点的依赖项检查,从而实现快速且与已安装插件的数量的扩展性。

独立管理器使用

有时可能需要更新缓存的入口点,例如

  • 在卸载插件后(目前setuptools没有卸载钩子)

  • 在安装不使用安装钩子的插件后

  • 在开发插件/插件宿主时

对于这些情况,Reentry有一个命令行界面

$ reentry --help
Usage: reentry [OPTIONS] COMMAND [ARGS]...

  manage your reentry python entry point cache

Options:
  --help  Show this message and exit.

Commands:
  clear  Clear entry point map.
  dev    Development related commands.
  map    Print out a map of cached entry points
  scan   Scan for python entry points to cache for faster loading.
$ reentry scan --help
Usage: reentry scan [OPTIONS] PATTERN

   Scan for python entry points to cache for faster loading.

   Scan only for specific PATTERNs or leave empty to scan all

Options:
   -r, --regex  Treat PATTERNs as regular expresions
   --help       Show this message and exit.
$ reentry map --help
Usage: reentry map [OPTIONS]

Options:
  --dist TEXT   limit map to a distribution
  --group TEXT  limit map to an entry point group
  --name TEXT   limit map to entrypoints that match NAME
  --help        Show this message and exit.

注意:在需要的地方(例如在jupyter笔记本中),这些操作也可以使用reentry manager在Python中执行,例如

from reentry import manager
manager.scan()

CLI示例

Reentry提供了iter_entry_points的替代方案

import click
from click_plugins import with_plugins
from reentry.manager import iter_entry_points

@with_plugins(iter_entry_points('cli_plugins'))
@click.group()
def cli():
   """
   command with subcommands loaded from plugin entry points
   """

为了使其工作,Reentry必须安装,并且必须使用它扫描过‘cli_plugins’组的入口点一次。

开发

运行测试

tox

创建发行版

tox -e py39-release

项目详情


下载文件

下载适用于您平台文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源分布

reentry-1.3.3.tar.gz (18.7 kB 查看散列)

上传时间

构建分布

reentry-1.3.3-py3-none-any.whl (17.6 kB 查看散列值)

上传时间 Python 3

由以下支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误日志 StatusPage StatusPage 状态页面