python - 如何动态添加和加载入口点?

标签 python plugins setuptools entry-point

我正在使用入口点开发带有插件的 slack 机器人。我想在运行时动态添加一个插件。

我有一个具有这种结构的项目:

+ ~/my_project_dir/
    + my_projects_python_code/
    + plugins/
        - plugin1.py
        - plugin2.py
        - ...
        - pluginN.py
    - setup.py
    - venv/
    - install.sh

我的 setup.py 文件如下所示:

from setuptools import setup, find_packages

setup(
    name="My_Project_plugins",
    version="1.0",
    packages=['plugins'],
    entry_points="""
        [my_project.plugins]
        plugin1 = plugins.plugin1:plugin1_class
        plugin2 = plugins.plugin2:plugin2_class
        ...
        pluginN = plugins.pluginN:pluginN_class
    """
        )

运行 sudo install.sh 执行以下操作:

  1. 将所需文件复制到 /usr/share/my_project_dir/

  2. /usr/share/my_project_dir/venv/bin/activate

  3. 激活virtualenv
  4. 运行:python setup.py develop

这按预期工作并正确设置了我的入口点,以便我可以通过机器人使用它们。

但我希望能够将插件添加到 setup.py 并能够在机器人运行时使用它。所以我想添加一行:pluginN+1 = plugins.pluginN+1:pluginN+1_class 并让 pluginN+1 可用。

我尝试/学到的东西:

  • /usr/share/my_project_dir/venv/bin/activate 之后,我打开一个 Python 交互式 shell 并遍历 pkg_resources.iter_entry_points(),它列出了从 setup.py 的初始状态加载的所有内容(即 plugin1 到 pluginN)

  • 如果我向 setup.py 添加一行并运行 sudo python setup.py develop 并使用相同的 Python shell 再次迭代,它不会选择新插件,但如果我退出 shell 并重新打开它,就会选择新插件。

  • 我注意到当我安装机器人时,部分输出显示:

    • 复制 My_Project_plugins-1.0-py2.7.egg 到/usr/share/my_project-dir/venv/lib/python2.7/site-packages
  • 当我 cd/usr/share/my_project_dir/ 时,激活我的 virtualenv,并从 shell 运行 setup.py 它说:

    • 创建/usr/local/lib/python2.7/dist-packages/My_Project-plugins.egg-link(链接到 .) My_Project-plugins 1.0 已经是 easy-install.pth 中的激活版本

最佳答案

为了测试目的,我需要做一些类似的事情来加载一个虚拟插件。这与您的用例略有不同,因为我特别试图避免需要在包中定义入口点(因为它只是测试代码)。

我发现我可以动态地将条目插入到 pkg_resources 数据结构中,如下所示:

import pkg_resources
# Create the fake entry point definition
ep = pkg_resources.EntryPoint.parse('dummy = dummy_module:DummyPlugin')

# Create a fake distribution to insert into the global working_set
d = pkg_resources.Distribution()

# Add the mapping to the fake EntryPoint
d._ep_map = {'namespace': {'dummy': ep}}

# Add the fake distribution to the global working_set
pkg_resources.working_set.add(d, 'dummy')

这在运行时添加了一个名为“dummy”的入口点到“namespace”,这将是“dummy_module.py”中的类“DummyPlugin”。

这是通过使用 setuptools 文档和对象上的 dir() 来根据需要获取更多信息来确定的。

文档在这里:http://setuptools.readthedocs.io/en/latest/pkg_resources.html

您可能会特别关注 http://setuptools.readthedocs.io/en/latest/pkg_resources.html#locating-plugins如果您需要做的就是加载您刚刚存储到本地文件系统的插件。

关于python - 如何动态添加和加载入口点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40514205/

相关文章:

java - 如何在PythonInterpreter(jython)中获取UTF-8阅读器?

python - 如何在 Python 中创建通用接口(interface)?

用于将 UserVoice 风格的反馈选项卡添加到网页的 jQuery 插件

python - 为什么安装 python 包会破坏 setuptools 并导致找不到 pkg_resources?

python - 可以阴谋地返回帐户的现有数字列表吗?

python - 重写Django queryset的Update方法

asp.net - 如何在插件中获取模拟用户 ID?

jquery - 寻找图像工具提示 jQuery 插件

python - 如何制作特定于平台的 Python 包?

python - 有没有一种可移植的方法来提供在 PyPI 上分发的包的本地化?