问题原贴: http://cloverprince.iteye.com/admin/blogs/481307
引用
5. 现有一个主程序用Python语言写成。现在要允许第三方开发人员编写扩展的类,约定第三方开发的类必须包含一个继承自某个已知类(如class FooPlugin)的子类,名称不限。如果要求第三方的类必须与主程序的py脚本或pyc字节码分开发布,把py或pyc丢在某个文件夹内即可被动态装载使用,应如何实现?
回答:
Python的imp模块提供了加载模块的方法。一旦加载了模块,其中的函数、类,就可以直接用成员运算符“.”访问。
适用范围:
Python2.x
实现:
Python是动态语言,定义接口不是必须的,只要你知道如何“对待”这些对象即可。
插件设计如下
一个插件:
def hello():
print "Hello world!"
class Hello():
def set_name(self,name):
self.name=name
def greet(self):
print "Hello, %s" % (self.name,)
plugin_class = Hello
最后一行,plugin_class是为了让不同的插件有相同的“接口”(程序员想象中的接口即可,即:知道这个类叫plugin_class这个名字)。
另一个插件
def hello():
print "Goodbye world!"
class Goodbye():
def set_name(self,name):
self.name=name
def greet(self):
print "Goodbye, %s" % (self.name,)
plugin_class = Goodbye
主程序只要装载它们。
import imp
import os
PLUGINS_PATH = "plugins"
SUFFIXES = [tup[0] for tup in imp.get_suffixes()]
def split_suffix(name):
for suffix in SUFFIXES:
if name.endswith(suffix):
return (name[:-len(suffix)],suffix)
return None
module_names = set(split_pair[0]
for split_pair
in map(split_suffix,os.listdir(PLUGIN_PATH))
if split_pair is not None)
plugin_modules = []
for module_name in module_names:
rv = imp.find_module(module_name,[PLUGINS_PATH])
if rv is not None:
mod = imp.load_module(module_name,*rv)
plugin_modules.append(mod)
for mod in plugin_modules:
mod.hello()
obj = mod.plugin_class()
obj.set_name("cloverprince")
obj.greet()
运行:
目录结构如下:
引用
.
│ main.py
│
└─plugins
goodbye.py
hello.py
执行结果:
引用
Hello world!
Hello, cloverprince
Goodbye world!
Goodbye, cloverprince
总结:
1. 主程序并不了解plugins目录中有多少插件。在运行时列举目录。
2. 主程序对每个plugins文件(比如叫hello.py)的了解只有:
- 这个模块中有一个叫做hello()的函数
- 这个模块中有一个类,名字虽然不知道,但是可以用plugin_class()这样的调用来获得实例(plugin_class不一定是类,也可以是工厂函数,Python运行时的语法都是plugin_class())
- 这个类的实例有set_name()和greet()两个方法。
分享到:
相关推荐
在电子设计大赛中,开发抽题小插件是一项常见的任务,用于随机选择参赛者需要解答的问题。本项目名为"C#抽题小插件",它采用C#编程语言实现,主要用于打开并处理PDF文件,这涉及到C#与PDF文档交互的技术。下面将详细...
首先,我们要明白手机端HTML5滑动选择题插件的主要目标是为用户提供一个流畅的、适应不同屏幕尺寸的选择题浏览和解答环境。这种插件通常具有响应式设计,能够自动适应手机、平板电脑等不同设备的屏幕大小。响应式...
《C++ Primer Plus 第五版 中文版课后习题答案详解》是针对C++初学者及进阶者的一份宝贵资源,它详尽解答了该书中的所有练习题,帮助读者巩固和深化对C++语言的理解。这本书的第五版在原有的基础上进行了更新和改进...
### 第十五届蓝桥杯大赛软件赛省赛第二场 C/C++ 大学B组试题解析 #### 题目背景及要求概述 蓝桥杯大赛是中国一项知名的计算机类竞赛,旨在选拔和培养优秀的计算机人才。本次比赛为第十五届蓝桥杯大赛软件赛省赛第...
2. **可扩展性**:设计为模块化、插件化,允许添加自定义功能和集成第三方服务,以满足不同场景的需求。 3. **自动化**:Kubernetes能够自动部署、重启、复制和扩展容器,确保服务的高可用性和稳定性。 Kubernetes...
假设“压缩包子文件的文件名称列表”中只出现了“05”,这可能是练习题集的分部分编号,表明当前进行到练习题集中的第五个部分,即“JS练习第三题代码”。在这一阶段,学习者应当仔细阅读题目要求,编写相应的...
本教程通过详细解答课后习题,帮助读者深入理解JavaWeb编程的核心概念和技术。以下是相关知识点的详细说明: 1. **JavaWeb基础**:JavaWeb是基于Java技术的Web应用开发平台,它包括Servlet、JSP(JavaServer Pages...
"计算机网络第五版试题及答案.pdf" 本资源是一个关于计算机网络的试题集,涵盖了计算机网络的基础知识和关键概念。通过回答这些问题,可以帮助学习者检查自己的知识水平和理解程度。 从试题的内容来看,涵盖了...
1~31 题目 + 完整解答代码 1.分秒转换 2.字符串转换为整数 3.最大最小数字的差值 4.列表最后一个元素 5.比较字符串长度 6.字符串首尾连接 7.检查复数单词 8.列表唯一的数字 9.range转为列表 10.素数判断 11.元音...
通信原理习题 第六章 数字信号的调制传输共3页,第2页2、已知解调器输入端的峰值信噪比为 8 dB,分别计算 2ASK 和 2PSK 相干解调的误比特率,并进行
"百度Android工程师面试题.zip" 这个标题表明这是一份与百度公司面试Android工程师相关的资料集合,通常包含常见的面试问题、技术要点以及可能的解答。这份资料可能涵盖了Android开发的基础到高级知识,旨在帮助应聘...
在第9届全国大学生GIS技能大赛中,下午的试题可能涵盖了GIS技术的多个核心领域,包括空间数据处理、地图制图、空间分析、数据库管理以及GIS应用开发等。 1. **空间数据处理**:这部分可能涉及到矢量数据的编辑和...
4. BIM设计师斑马的背景:斑马拥有浙江大学建筑系的硕士学历和在国企设计院及上市公司的BIM工作经验,代表作品包括参加第16届威尼斯建筑双年展的华腾猪舍里展厅以及入选2014年Rhino大会的沈阳科技馆幕墙项目。...
通信原理习题 第五章 数字信号的基带传输共 4页,第 2页2、已知某数字代码序列对应的 CMI 码基带信号波形如图所示,画出对应的 HDB3 码基带信号的波形,
- 第四、五题是C语言程序填空,测试考生的结构化编程能力,数据结构和算法运用。 - 第六、七题为C++和Java程序填空,考生需选择一题,用所选语言实现常见设计模式和应用程序。 3. **考试策略**: - 数据流图设计...
本文主要讨论了两个编程相关的课堂练习题,涵盖了16位汇编语言的程序设计和子程序调用。首先,我们来详细分析第一个题目。 题目一的目标是编写一个汇编程序段,将BX寄存器中的内容以十六进制形式显示在屏幕上。这个...
通过解答《Thinking in Java》第四版的练习题,我们可以系统地巩固和提高Java编程技能,为成为一名出色的Java开发者打下坚实基础。这本书的习题涵盖了从基础到高级的各个方面,是每个Java学习者不可多得的实践资源。
5. **数据结构**:码图问题通常涉及到图的数据结构,如邻接矩阵和邻接表。理解如何在C++中表示和操作这些数据结构是解决问题的关键。 6. **算法**: - **图遍历**:深度优先搜索(DFS)和广度优先搜索(BFS)是解决码...
5. **JDBC**:Java Database Connectivity是Java访问数据库的标准接口,包括连接数据库、执行SQL语句、处理结果集等。掌握数据库连接池的使用,如C3P0、DBCP或 Druid,以及预编译语句(PreparedStatement)的应用。 ...
- 第5题涉及到积分次序的转换和积分的计算。 - 第6题涉及微分方程的特解形式,需要根据特征根设定特解的形式。 - 第7题是球面方程的确定,需要知道球心坐标和球通过原点的信息。 - 第8题考察极限及其与连续性的...