代码之家  ›  专栏  ›  技术社区  ›  mac

如何组织我已经工作的插件系统的文件结构?

  •  5
  • mac  · 技术社区  · 16 年前

    我正在做一个项目,其主要设计指导原则是可扩展性。

    我通过定义一个元类来实现一个插件系统,这个元类使用一个类方法来注册加载的任何插件的类名 (每种类型的插件都继承自核心代码中定义的特定类,因为应用程序中有不同类型的插件)。基本上这意味着开发人员必须将其类定义为

    class PieChart(ChartPluginAncestor):
        # Duck typing:
        # Implement compulsory methods for Plugins 
        # extending Chart functionality
    

    主程序会知道他的存在,因为 PieChart 将包含在注册插件列表中 ChartPluginAncestor.plugins 是的。

    作为一个类方法的挂载方法,所有的插件在它们的类代码被加载到内存中时都会被注册(所以即使在类的对象被实例化之前) 是的。

    系统工作正常 足够好了 –对我来说(尽管我总是乐于接受关于如何改进体系结构的建议!)但我现在想知道什么是管理插件文件的最佳方式(即。 包含插件的文件应存储在何处以及如何存储 )中。

    到目前为止,为了开发的目的,我正在使用一个我称之为“插件”的包。我把所有包含插件类的*.py文件放在package目录中,然后简单地发出 import plugins 在main.py文件中,为所有插件正确安装。

    编辑: 杰夫在评论中指出 导入插件 包的各个模块中包含的类将不容易获得(我没有意识到这一点,因为为了调试的目的,我是用 from plugins.myAI import AI )中。

    但是,只有在我开发和测试代码时,这个系统才是好的,因为:

    • 插件可能带有自己的单元测试,我不想在内存中加载它们。
    • 所有插件当前都加载到内存中,但确实有某些插件是同一功能的替代版本,因此您只需知道可以在这两个插件之间切换,但您只需要将从配置窗格中选择的插件加载到内存中。
    • 在某种程度上,我希望有一个安装插件的双重位置:一个系统范围的位置(例如 /usr/local/bin/ )以及用户特定的(例如 /home/<user>/.myprogram/ )中。

    所以我的问题可能有三个:

    1. 插件容器: 对于我的目标,最明智的选择是什么?单个文件?包装?一个简单的.py文件目录?)
    2. 在不必加载(导入)插件的情况下识别插件的存在: 使用python内省来执行此操作的聪明方法是什么?
    3. 在两个不同的位置放置插件: 有没有一种标准的方法/最佳实践(至少在gnu/linux下)来做到这一点?
    2 回复  |  直到 8 年前
        1
  •  3
  •   daitangio    16 年前

    这个问题很难解决,因为需求很复杂。 不管怎样,我会尝试一些建议。

    关于

    将插件放在两个不同的 地点:有标准的方法吗/ 最佳实践(在gnu/linux下,在 至少)这样做?

    一个好的方法是virtualenv。virtualenv是一个构建“独立”python安装的python模块。这是让不同项目一起工作的更好方法。 你得到一个全新的网站包,你可以把你的插件与相关的项目模块。

    试试看: http://pypi.python.org/pypi/virtualenv

    插件容器:什么是最 为我的目标做出明智的选择?单一的 文件夹?包装?一个简单的目录 .py文件?)

    一个好的方法是python包,它可以在导入时进行“自注册”:只需在包目录中定义一个适当的 初始 .py年

    一个例子可以是 http://www.qgis.org/wiki/Writing_Python_Plugins 以及这里描述的api http://twistedmatrix.com/documents/current/core/howto/plugin.html

    另见 http://pypi.python.org/pypi/giblets/0.2.1

    Giblets是一个简单的插件系统 基于 特雷克。简而言之,giblets允许 声明接口并发现 在没有 耦合。

    Giblets还包括插件发现 基于文件路径或入口点 以及灵活的管理手段 哪些组件已启用或 在应用程序中禁用。

        2
  •  1
  •   minou    16 年前

    我也有一个插件系统,有三种类型的插件,虽然我不声称做得很好。你可以看到一些细节 here 是的。

    对于内部插件,我有一个包(例如, MethodPlugins )在这个包中是每个插件的一个模块(例如, MethodPlugins.IRV )中。下面是我如何加载插件的:

    1. 装入程序包( import MethodPlugins )

    2. 使用 pkgutil.iter_modules 加载所有模块(例如, 方法插件.irv )

    3. 所有的插件都来自一个公共基类,所以我可以使用 __subclassess__ 把他们都认出来。

    我相信这可以让你在不加载插件的情况下识别插件,尽管我并不是这样做的,因为我只是加载它们而已。

    对于外部插件,我有一个指定的目录,用户可以在其中放置它们,我使用 os.listdir 以导入它们。用户必须使用正确的基类,这样我才能找到它们。

    我也有兴趣改进这个,但它对我来说也足够好了。:)