stevedore动态加载模块,stevedore使用setuptools的entry points来定义并加载插件。entry point引用的是定义在模块中的对象,比如类、函数、实例等,只要在import模块时能够被创建的对象都可以,但stevedore的优良之处在于,其可以动态调用所有插件的某一相同方法,将返回结果存入list中。这对于处理具有相同行为的类,起到极大的便利。

如何构建插件?

先定义一个基类,所有继承该基类的子类既为各个独立的插件。

import abc
import six
# 定义基类,只包含format方法,文件路径 plugins/
@six.add_metaclass(abc.ABCMeta)
class FormatterBase(object): @abc.abstractmethod
def format(self, data):
pass

定义一个插件Simple,实现format方法

 from plugins import plugin_base
# 文件路径 plugins/simple.py
class Simple(plugin_base.FormatterBase): data = {'ca':'cangyue', "name":"caesar"} def format(self, data):
lines = []
for name, value in sorted(data.items()):
line = '{name}={value}'.format(
name = name,
value = value
)
lines.append(line)
return ''.join(lines)

编写setup.py文件,用于发布包。 包名demo,版本0.1, 组名stevedore.formatter  两个插件simple和plain都对应Plugins.simple路径中的Simple类。文件路径与plugins同路径,注意plugins中有空__init__.py文件,

表示是一个python包。

 from setuptools import setup, find_packages
setup(
name = "demo",
version = "0.1",
packages = find_packages(),
entry_points={
'stevedore.formatter': [
'simple = plugins.simple:Simple',
'plain = plugins.simple:Simple',
],
},
)

使用命令发布包 python setup.py install 安装,安装后会在egg文件夹下生成entry_points.txt文件,描述组名和插件

[stevedore.formatter]
simple = plugins.simple:Simple
plain = plugins.simple:Simple

如何调用插件中方法?

1.加载某一插件,并调用其中方法

 from stevedore import driver
mgr = driver.DriverManager(
namespace='stevedore.formatter',
name='simple',
invoke_on_load=True
) # 加载组名或者说命名空间为stevedore.formetter下name为simple的插件
>>> st = mgr.driver.format({'caesa':'sss'})
>>> data = mgr.driver.data # mgr.driver实例化simple对象并调用其data属性
>>> print data
10 {'ca': 'cangyue', 'name': 'caesar'}

2.加载命名空间下所有插件,并调用所有插件的format方法

 from stevedore import extension
mgr = extension.ExtensionManager(
namespace='stevedore.formatter',
invoke_on_load=True) # 加载stevedore.formatter命名空间下所有插件 def d(ext):
return ext.obj.data >>> dat = mgr.map(d) #对所有插件调用d方法,d方法中ext为插件的extension对象,调用其obj即可实例化该对象
>>> print dat
[{'ca': 'cangyue', 'name': 'caesar'}, {'ca': 'cangyue', 'name': 'caesar'}] def m(ext):
data = ext.obj.data #获取插件对象的data属性值
return ext.obj.format(data) 调用对象的format方法,将属性值传入 >>> ret = mgr.map(m)
>>> print ret
['ca=cangyuename=caesar', 'ca=cangyuename=caesar']

特记:

当想重新开发一个插件时,需要在编写完成后,重新安装,否则不生效。比如鄙人想重新开发一个complex,在相应路径下添加complex.py

在entry_point中添加插件

但重新执行时,加载的仍然是两个插件

参考文献: http://blog.csdn.net/qingyuanluofeng/article/details/72853465

stevedore动态加载模块的更多相关文章

  1. OrchardCore 如何动态加载模块?

    前言 今天,我们再次讨论下OrchardCore,通过初期调研,我们项目采用OrchardCore底层设施支持模块化,同时根据业务场景,额外还需支持二次开发,于是有了本文,若有不同解决方案,欢迎留言探 ...

  2. Python_getattr+__import__ 实现动态加载模块、类对象或函数

    __import__() 语法 __import__(name[, globals[, locals[, fromlist[, level]]]]) 参数 name -- 字符串,模块的导入路径 说明 ...

  3. AngularJs 动态加载模块和依赖

    最近项目比较忙额,白天要上班,晚上回来还需要做Angular知识点的ppt给同事,毕竟年底要辞职了,项目的后续开发还是需要有人接手的,所以就占用了晚上学习的时间.本来一直不打算写这些第三方插件的学习笔 ...

  4. [driver]linux内核动态加载模块

    问题: 1. 把编译好的模块放到板子/lib/modules对应文件夹下,并且执行了depmod -a, 比如pl2303.ko, 那么下一次插入pl2303的串口线,是否可以识别,也就是自动加载pl ...

  5. angular-ui-router动态加载模块

    1.定义index.html主页,对于通用的js就不用require依赖加载了,其中main.js作为主模块,用require添加系统路由模块. <!DOCTYPE html> <h ...

  6. nginx平滑升级、在线添加模块(tengine 动态加载模块)

    http://www.orzace.com/how-to-upgrade-nginx/ 下面是nginx替换成tengine再加上lua 模块,(tengine-2.0.1版本暂时无法动态加载lua模 ...

  7. Apache动态加载模块

    添加步骤:如要额外安装cgi,先找到mod_cgi.c及mod_cgid.c.一般在apache安装包目录下,如 ./httpd-2.2.25/modules/generators .#编译安装 cg ...

  8. ubuntu动态加载模块简单模板

    1:简单代码 #include<linux/init.h> #include<linux/module.h> MODULE_LICENSE("GPL"); ...

  9. 配置动态加载模块和js分模块打包,生产环境和开发环境公共常量配置

    1. 话不多少 先上代码:  route.js  // 引用模板 分模块编译 const main = r => require.ensure([], () => r(require('. ...

随机推荐

  1. Debug版本正常运行,Release版本编译通过但运行崩溃

    解决这个问题之前,第一个想的是Debug版本和Release版本有什么区别 Debug版: 经过编译器编译出的项目.exe文件大,而且生成的二进制命令没有经过编译器的优化.项目中包含着丰富的调试信息, ...

  2. python-GIL

    全局解释器锁GIL:在同一时刻仅有一个线程可被调度执行.对于单核环境,该实现简单高效.对于多线程的并发应用,一般通过多进程加协程充分发挥多核计算能力. 对于I/O密集型任务,线程发生阻塞时,会自动释放 ...

  3. [Android]Android布局优化之 ViewStub

    转载请标注:转载于http://www.cnblogs.com/Liuyt-61/p/6602926.html -------------------------------------------- ...

  4. Android呼吸灯效果实现

    最近需要做一个搜索动画的呼吸灯效果,在网上查了下有以下两种实现方式,现记录下来. 实现呼吸灯效果本质上都是使用ImageView动画,实现alpha值变化. 第一种方式,直接使用动画实现,代码如下: ...

  5. ARP 欺骗攻击与防御

    <一> ARP攻防 理论 和 工具 工具: 01: Wireshark ( 抓包软件 )   02: P2P终结者 ( ARP欺骗工具 )   03: cain & abel  ( ...

  6. 通过Sonar的代码质量报告学习【如何写安全高质量的代码】

    1.不要用.size(),改用isEmpty() Using Collection.size() to test for emptiness works, but using Collection.i ...

  7. electron安装到第一个实例

    1.node.js下载,然后安装.下载地址:链接:http://pan.baidu.com/s/1o7TONhS 密码:fosa 2.cmd下输入:npm install electron-prebu ...

  8. Unicode UTF8 UTF16 urlencode base64

    Unicode:是一个字符集,每个字符对应一个唯一的unicode编码,一般是16位. UTF8是针对Unicode的编码方式,因为如果每个字符都用unicode的编码存储的话会很浪费空间,比如说as ...

  9. Delphi 三层TDataSetProvider

    在Delphi想使用三层架构或者使用TClientDataSet控件,一般都需要引用TDataSetProvider控件,现对TDataSetProvider控件的Options属性值做一个简单的分析 ...

  10. openresty(完整版)Lua拦截请求与响应信息日志收集及基于cjson和redis动态路径以及Prometheus监控(转)

    直接上文件 nginx.conf #运行用户和组,缺省为nobody,若改为别的用户和组,则需要先创建用户和组 #user wls81 wls; #开启进程数,一般与CPU核数等同 worker_pr ...