dF.*_*dF. 182 python architecture plugins
我有一个用Python编写的应用程序,由相当技术的读者(科学家)使用.
我正在寻找一种让用户可以扩展应用程序的好方法,即脚本/插件架构.
我正在寻找非常轻量级的东西.大多数脚本或插件不会由第三方开发和分发并安装,但会在几分钟内被用户掀起,以自动执行重复任务,添加对文件格式的支持,所以插件应该具有绝对最小的样板代码,并且除了复制到文件夹之外不需要"安装"(因此像setuptools入口点或者Zope插件架构似乎太多了.)
是否有任何这样的系统,或任何实施类似计划的项目,我应该考虑一下想法/灵感?
TJG*_*TJG 145
我的基本上是一个名为"plugins"的目录,主应用程序可以轮询,然后使用imp.load_module来获取文件,查找一个众所周知的入口点,可能有模块级配置参数,然后从那里开始.我使用文件监控的东西来获得插件处于活动状态的一定程度的动态,但这是一个很好的选择.
当然,任何要求都说:"我不需要[大而复杂的东西] X;我只想要一些轻量级的东西"冒着一次重新实现X一个被发现的要求的风险.但这并不是说你无论如何都无法做到这一点:)
dbr*_*dbr 53
module_example.py
:
def plugin_main(*args, **kwargs):
print args, kwargs
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
它肯定是"最小的",它绝对没有错误检查,可能是无数的安全问题,它不是很灵活 - 但它应该向你展示Python中的插件系统是多么简单..
你可能要考虑的小鬼模块也一样,虽然你可以做很多事只是__import__
,os.listdir
和一些字符串操作.
Nic*_*zet 25
虽然这个问题非常有趣,但我认为如果没有更多细节,就很难回答.这是什么类型的应用程序?它有GUI吗?它是一个命令行工具吗?一组脚本?一个具有唯一入口点等的程序......
鉴于我所拥有的信息很少,我将以非常通用的方式回答.
你有什么方法可以添加插件?
在纯粹的代码/设计实践中,您必须清楚地确定您希望用户扩展的行为/特定操作.确定将始终被覆盖的公共入口点/一组功能,并确定这些操作中的组.完成后,应该可以轻松扩展您的应用程序,
使用钩子的例子,灵感来自MediaWiki(PHP,但语言真的很重要吗?):
import hooks
# In your core code, on key points, you allow user to run actions:
def compute(...):
try:
hooks.runHook(hooks.registered.beforeCompute)
except hooks.hookException:
print('Error while executing plugin')
# [compute main code] ...
try:
hooks.runHook(hooks.registered.afterCompute)
except hooks.hookException:
print('Error while executing plugin')
# The idea is to insert possibilities for users to extend the behavior
# where it matters.
# If you need to, pass context parameters to runHook. Remember that
# runHook can be defined as a runHook(*args, **kwargs) function, not
# requiring you to define a common interface for *all* hooks. Quite flexible :)
# --------------------
# And in the plugin code:
# [...] plugin magic
def doStuff():
# ....
# and register the functionalities in hooks
# doStuff will be called at the end of each core.compute() call
hooks.registered.afterCompute.append(doStuff)
Run Code Online (Sandbox Code Playgroud)
另一个例子,灵感来自于mercurial.这里,扩展只向hg命令行可执行文件添加命令,从而扩展了行为.
def doStuff(ui, repo, *args, **kwargs):
# when called, a extension function always receives:
# * an ui object (user interface, prints, warnings, etc)
# * a repository object (main object from which most operations are doable)
# * command-line arguments that were not used by the core program
doMoreMagicStuff()
obj = maybeCreateSomeObjects()
# each extension defines a commands dictionary in the main extension file
commands = { 'newcommand': doStuff }
Run Code Online (Sandbox Code Playgroud)
对于这两种方法,您可能需要对扩展程序进行常规初始化和最终确定.您可以使用所有扩展必须实现的通用接口(更适合第二种方法; mercurial使用为所有扩展调用的reposetup(ui,repo)),或者使用钩子方法,使用hooks.setup钩子.
但同样,如果你想要更多有用的答案,你将不得不缩小你的问题;)
beh*_*all 11
我是一名退休的生物学家,负责处理数字微图像,并发现自己必须编写一个图像处理和分析软件包(技术上不是库)才能在SGi机器上运行.我用C编写代码并使用Tcl作为脚本语言.GUI就像使用Tk一样完成.Tcl中出现的命令的格式为"extensionName commandName arg0 arg1 ... param0 param1 ...",即简单的空格分隔的单词和数字.当Tcl看到"extensionName"子字符串时,控件被传递给C包.然后通过词法分析器/解析器(在lex/yacc中完成)运行命令,然后根据需要调用C例程.
操作包的命令可以通过GUI中的窗口逐个运行,但批处理作业是通过编辑有效Tcl脚本的文本文件完成的; 您将选择执行您想要执行的文件级操作的模板,然后编辑副本以包含实际的目录和文件名以及包命令.它就像一个魅力.直到 ...
1)世界转向PC和2)脚本超过大约500行,当Tcl的组织能力开始变得非常不便时.时间飞逝 ...
我退休了,Python被发明了,它看起来像是Tcl的完美继承者.现在,我从来没有做过端口,因为我从来没有遇到过在PC上编译(相当大)的C程序,用C包扩展Python,以及在Python/Gt?/ Tk中做GUI的挑战? ?.但是,拥有可编辑模板脚本的旧想法似乎仍然可行.此外,以本机Python形式输入包命令不应该是太大的负担,例如:
packageName.command(arg0,arg1,...,param0,param1,...)
一些额外的点,parens和逗号,但那些不是showstoppers.
我记得有人在Python中完成了lex和yacc的版本(尝试:http://www.dabeaz.com/ply/),所以如果仍然需要它们,那么它们就在身边.
这种漫无边际的观点是,在我看来,Python本身就是科学家们可以使用的理想的"轻量级"前端.我很想知道为什么你认为它不是,我的意思是认真的.
后来添加:应用程序gedit预计插件被添加,他们的网站有一个简单的插件程序的最清楚的解释,我发现在几分钟的环顾四周.尝试:
https://wiki.gnome.org/Apps/Gedit/PythonPluginHowToOld
我还是想更好地理解你的问题.我不清楚您是否1)希望科学家能够以各种方式简单地使用您的(Python)应用程序,或2)希望科学家能够为您的应用程序添加新功能.选择#1是我们面对图像的情况,这导致我们使用我们修改的通用脚本以满足当下的需要.是选择#2引导您了解插件的概念,还是应用程序的某些方面使得发布命令变得不可行?
edo*_*aur 11
Marty Allchin的简单插件框架是我根据自己的需要使用的基础.我真的建议你去看看它,如果你想要一些简单易用的东西,我认为这是一个很好的开始.您也可以将它看作Django Snippets.
gun*_*sus 10
当我搜索Python装饰器时,找到了一个简单但有用的代码片段.它可能不符合您的需求,但非常鼓舞人心.
class TextProcessor(object):
PLUGINS = []
def process(self, text, plugins=()):
if plugins is ():
for plugin in self.PLUGINS:
text = plugin().process(text)
else:
for plugin in plugins:
text = plugin().process(text)
return text
@classmethod
def plugin(cls, plugin):
cls.PLUGINS.append(plugin)
return plugin
@TextProcessor.plugin
class CleanMarkdownBolds(object):
def process(self, text):
return text.replace('**', '')
Run Code Online (Sandbox Code Playgroud)
processor = TextProcessor()
processed = processor.process(text="**foo bar**", plugins=(CleanMarkdownBolds, ))
processed = processor.process(text="**foo bar**")
Run Code Online (Sandbox Code Playgroud)