Python插件系统

Python插件系统,python,plugins,Python,Plugins,我正在构建一个自定义语音识别,为此我定义了一个命令界面。这个想法是语音识别返回一个字符串,我得到了所有受支持命令的列表。然后我会浏览列表,找到最匹配的一个并执行它 为了保持代码的可维护性,我想创建一个插件系统,在这个系统中,您可以在一个单独的文件中定义一个从ICommand派生的类。文件夹结构如下所示: project/ ├── ICommand ├── commands/ │ ├── command1.py (inherits ICommand) │ ├── command2.py (

我正在构建一个自定义语音识别,为此我定义了一个命令界面。这个想法是语音识别返回一个字符串,我得到了所有受支持命令的列表。然后我会浏览列表,找到最匹配的一个并执行它

为了保持代码的可维护性,我想创建一个插件系统,在这个系统中,您可以在一个单独的文件中定义一个从ICommand派生的类。文件夹结构如下所示:

project/
├── ICommand
├── commands/
│   ├── command1.py (inherits ICommand)
│   ├── command2.py (inherits ICommand)  
我在这方面面临多个问题:

  • 如何在command1.py文件中导入ICommand进行继承

  • 如何在commands文件夹中为.py文件中包含的每个类创建一个实例

  • 有没有办法确保插件文件只包含派生ICommand类的定义

    • 如何在command1.py文件中导入ICommand进行继承
    你的项目必须在一个合适的包内。如果你还没有这样做,你应该这样做。 一旦Python了解到“command1”在包中,您就可以在包中执行以下操作:

    from ..ICommand import ICommand
    
    (当然,ICommand必须是定义ICommand的.py文件)

    • 如何为.py文件中包含的每个类创建一个实例 在“命令”文件夹中
    对于Python,除非显式导入文件,.py文件与目录中的任何数据文件一样好。该语言允许您对插件下的任何文件执行任何“自动发现”,但不执行任何“自动发现”

    您可以自己做这件事,您可以使用一个框架来做这类事情-
    zope.configuration
    就是其中之一,但是您必须用它应该扫描的文件夹创建类似xml的文件

    自己动手可以很容易,只需列出所需的文件夹,并调用
    \uuuuuu import\uuuu
    获取其中的任何Python文件。 t调用
    \uuuu import\uuuu
    返回的对象是模块本身,您只需检查其内容中的子类(或其他实现)
    ICommand
    ,然后实例化即可

    module = __import__(...)
    plugins = {}
    for name, obj in module.__dict__.items():
        if isinstance(obj, ICommand):
             plugins[name] = obj()   # This instatiate the class
    
    我有两个答案,并以明确的例子说明如何做到这一点:

    • 有没有办法确保插件文件只包含 派生ICommand类的定义

    但你不应该像你所说的那样把这个限制放在那里。 上面获取ICommand子类的代码片段检查所有modues顶级内容,您可以很容易地对任何不属于ICommand子类的变量、函数或类引发异常。 然而,这并不是一个合理的限制:在Python中,通常需要不与类相关的小“实用程序”函数,或者其他将保持常量值的变量——将它们约束为插件的类成员是没有用的。同样,如果您担心插件包含不应该存在的任意代码:您根本无法阻止。在Python进程中安全地“沙箱”Python文件是不可行的。非常优秀的人多年来一直试图拥有一个“Python沙盒”,但最终都失败了。(如果这是一项要求,请使用O.S.级别的流程资源限制,并在具有这些限制的流程中运行插件,即仅导入其文件)


    否则,您的意思可能是希望“每个文件有一个ICommand子类”,没有其他限制:然后在上面的循环中插入一个检查来实例化插件-如果它在同一个文件中找到第二个类,则引发异常

    非常感谢你,我要试试看。