我有一个用Python编写的应用程序,它是由相当专业的观众(科学家)使用的。

我正在寻找一个好方法,使应用程序可扩展的用户,即脚本/插件架构。

I am looking for something extremely lightweight. Most scripts, or plugins, are not going to be developed and distributed by a third-party and installed, but are going to be something whipped up by a user in a few minutes to automate a repeating task, add support for a file format, etc. So plugins should have the absolute minimum boilerplate code, and require no 'installation' other than copying to a folder (so something like setuptools entry points, or the Zope plugin architecture seems like too much.)

是否已经有类似的系统存在,或者是否有项目实现了类似的方案,我应该看看想法/灵感?


当前回答

I am a retired biologist who dealt with digital micrograqphs and found himself having to write an image processing and analysis package (not technically a library) to run on an SGi machine. I wrote the code in C and used Tcl for the scripting language. The GUI, such as it was, was done using Tk. The commands that appeared in Tcl were of the form "extensionName commandName arg0 arg1 ... param0 param1 ...", that is, simple space-separated words and numbers. When Tcl saw the "extensionName" substring, control was passed to the C package. That in turn ran the command through a lexer/parser (done in lex/yacc) and then called C routines as necessary.

操作包的命令可以通过GUI中的窗口逐一运行,但批作业是通过编辑文本文件完成的,这些文本文件是有效的Tcl脚本;您可以选择执行您想要执行的文件级操作的模板,然后编辑一个副本,以包含实际的目录和文件名以及包命令。这招很管用。直到……

1)世界转向了pc, 2)脚本超过了500行,这时Tcl不稳定的组织能力开始成为真正的不便。时间流逝……

我退休了,Python被发明了,它看起来像是Tcl的完美继承者。现在,我从来没有做过移植,因为我从来没有面对过在PC上编译(相当大的)C程序,用C包扩展Python,用Python/Gt?/Tk?/??做gui的挑战。然而,拥有可编辑模板脚本的旧想法似乎仍然可行。此外,以原生Python形式输入包命令也不应该是太大的负担,例如:

packageName.command(arg0, arg1,…, param0, param1,…)

一些额外的点、连号和逗号,但这些都不能阻止表演。

我记得看到有人用Python完成了lex和yacc的版本(请尝试:http://www.dabeaz.com/ply/),所以如果仍然需要它们,它们就在附近。

本文的重点在于,在我看来,Python本身就是科学家所期望的“轻量级”前端。我很好奇为什么你不这么认为,我是认真的。


后来添加的:应用程序gedit预计会添加插件,他们的网站对一个简单的插件过程有最清晰的解释,我花了几分钟的时间就找到了。试一试:

https://wiki.gnome.org/Apps/Gedit/PythonPluginHowToOld

I'd still like to understand your question better. I am unclear whether you 1) want scientists to be able to use your (Python) application quite simply in various ways or 2) want to allow the scientists to add new capabilities to your application. Choice #1 is the situation we faced with the images and that led us to use generic scripts which we modified to suit the need of the moment. Is it Choice #2 which leads you to the idea of plugins, or is it some aspect of your application that makes issuing commands to it impracticable?

其他回答

我的是,基本上,一个名为“plugins”的目录,主应用程序可以轮询,然后使用imp.load_module来拾取文件,寻找一个已知的入口点,可能是模块级配置参数,然后从那里开始。我使用文件监控的东西来实现一定程度的动态,其中插件是活跃的,但这是一个很好的拥有。

当然,任何出现的要求都是“我不需要(大而复杂的东西)X;我只是想要一些轻量级的东西”会冒着一次重新实现一个已发现需求的风险。但这并不是说你不能从中获得乐趣。

看看这个对现有插件框架/库的概述,这是一个很好的起点。我很喜欢yapsy,但这取决于你的用例。

你也可以看看“基础工作”。

其思想是围绕可重用组件(称为模式和插件)构建应用程序。插件是派生自GwBasePattern的类。 这里有一个基本的例子:

from groundwork import App
from groundwork.patterns import GwBasePattern

class MyPlugin(GwBasePattern):
    def __init__(self, app, **kwargs):
        self.name = "My Plugin"
        super().__init__(app, **kwargs)

    def activate(self): 
        pass

    def deactivate(self):
        pass

my_app = App(plugins=[MyPlugin])       # register plugin
my_app.plugins.activate(["My Plugin"]) # activate it

还有更高级的模式来处理命令行接口、信号或共享对象。

foundation可以通过编程方式将插件绑定到应用程序中,如上面所示,也可以通过setuptools自动查找插件。包含插件的Python包必须使用一个特殊的入口点groundwork.plugin声明这些插件。

这是文件。

免责声明:我是《基础》的作者之一。

module_example.py:

def plugin_main(*args, **kwargs):
    print args, kwargs

loader.py:

def load_plugin(name):
    mod = __import__("module_%s" % name)
    return mod

def call_plugin(name, *args, **kwargs):
    plugin = load_plugin(name)
    plugin.plugin_main(*args, **kwargs)

call_plugin("example", 1234)

它当然是“最小的”,它绝对没有错误检查,可能有无数的安全问题,它不是很灵活-但它应该告诉你一个Python插件系统可以多么简单。

你可能也想看看imp模块,尽管你可以用__import__, os。Listdir和一些字符串操作。

I arrived here looking for a minimal plugin architecture, and found a lot of things that all seemed like overkill to me. So, I've implemented Super Simple Python Plugins. To use it, you create one or more directories and drop a special __init__.py file in each one. Importing those directories will cause all other Python files to be loaded as submodules, and their name(s) will be placed in the __all__ list. Then it's up to you to validate/initialize/register those modules. There's an example in the README file.