【Python Package】
Package是python用名字空间组织module的一种方法,通过"."将各级路径连接起来,以"A.B.C"的形式组成层次结构。每一个python文件是一个module,包含module的目录可以组成一个package,包含package的目录又可以进一步组成更高级的package。
【package基本结构】
不是所有的目录都会被解释为package,其充要条件是目录内包含一个名为__init __.py的文件,这个文件可以是空文件,也可以包含一些定义和初始化代码,包含该文件的目录可以被import。如下目录可以被作为package使用,本例中除了__init __.py文件外,还包含三个module。
myprint/
|---__init__.py
|---print_int.py
|---print_float.py
|---print_complex.py
因为myprint目录下有__init__.py文件,myprint是一个package,可以在python代码或命令行中import它及它包含的module。
import myprint # import了一个package
或
import myprint.print_int # import了package下的一个module
或
from myprint import print_int # import了package下的一个module,引用时可以不带package name
【subpackage】
Packages可以形成多层嵌套的结构,tensorflow代码中经常看到import多层的情况。下例中tensorflow、python、framework都是上一层namespace中的package,只有ops是module。
import tensorflow.python.framework.ops
如果有import A.B.C.D,只有D可以是module,A、B、C都必须是package。
【__ init __ 文件】
文件__init.py让python将其所属目录视为package,该文件可以是空文件,也可以包含python代码,文件内的代码在package第一次被进程import时执行一次。文件__init__.py中定义的函数、变量,可以通过package name被外部引用。如果上面例子中myprint/__init.py包含如下代码,则default_int和default_float两个名字可以通过myprint.default_int和myprint.default_float访问。
__all__ = ['print_int', 'print_float']
default_int = 0
default_float = 0.0
import myprint
myprint.print_int
myprint.print_float
如果import的是一个subpackage,则路径上所有package的__init__.py文件会被依次执行。例如,当import A.B.C.D时,A package、B package、C package会被先后初始化,如果D也是package,则D package也会被初始化。
init.py文件中还可以定义__all__变量,如上面代码中有__all__ = [‘print_int’, ‘print_float’],当通过代码from myprint import *导入package时,只有__all__中定义的所有name会被导入,而不是把myprint/目录下的所有东西都导入。__all__中定义的name是package下的module或subpackage。
【插件动态加载实现1】
目录结构:
|-main.py
|-plugins/
|-plugins/__init__.py
|-plugins/plugin1.py
|-plugins/plugin2.py
|-plugins/__init __.py
__all__ = ['plugin1', 'plugin2']
|-plugins/plugin1.py
class Plugin1:
def setPlatform(self, platform):
self.platform=platform
def start(self):
self.platform.sayHello("plugin1")
def stop(self):
self.platform.sayGoodbye("plugin1")
def getPluginClass():
return Plugin1
|-plugins/plugin2.py
def sayGoodbye(self, from_):
print "goodbye from %s." % from_
class Plugin2:
def setPlatform(self, platform):
self.platform=platform
if platform=platform
platform.__class__.sayGoodbye=sayGoodbye
def start(self):
self.platform.sayHello("plugin2")
def stop(self):
self.platform.sayGoodbye("plugin2")
def getPluginClass():
return Plugin2
|-main.py
import os
class Platform:
def __init__(self):
self.plugins=[]
self.loadPlugins()
def sayHello(self, from_):
print "hello from %s." % from_
def loadPlugins(self):
print "********** loadPlugins **********"
print "listdir(plugins): ", os.listdir("plugins")
for filename in os.listdir("plugins")
if not filename.endswith(".py") or filename.startswith("_")
continue
self.runPlugin(filename)
def runPlugin(self, filename):
print "********** runPlugin **********"
pluginName=os.path.splitext(filename)[0]
print 'pluginName: ', pluginName
plugin=__import__("plugins."+pluginName, fromlist=[pluginName])
clazz=plugin.getPluginClass()
o=clazz()
print 'clazz: ', clazz
o.start()
self.plugins.append()
def shutdown(self):
for o in self.plugins:
o.stop()
o.setPlatfrom(None)
self.plugins=[]
if __name__=="__main__":
platform=Platform()
platform.shutdown()
【插件动态加载实现2】
|-main.py
|-plugins/
|-plugins/__init__.py
|-plugins/_01plugin.py
|-plugins/_02plugin.py
|-plugins/_03plugin.py
|-plugins/_04plugin.py
|-plugins/...
|-plugins/_98plugin.py
|-plugins/_99plugin.py
|-plugins/__init __.py
import os
import pkgutil
pkgpath = os.path.dirname(__file__)
pkgname = os.path.basename(pkgpath)
for _, file, _ in pkgutil.iter_modules([pkgpath]):
abfile = os.path.join(pkgpath, file)
__import__(pkgname+'.'+file)
__all__ = [ '_01plugin',
'_02plugin',
'_03plugin',
'_04plugin',
...,
'_98plugin',
'_99plugin'
|-plugins/_0*plugin.py
class Parse
def __init__(self):
def parse(self):
def render(self):
def getPluginClass():
return Parser
|-main.py
import os
class Platform:
def __init__(self, filename):
self.plugins = []
self.loadPlugins()
self.zipfilename = filename
def loadPlugins(self):
base_path = os.path.dirname(os.path.abspath(__file__))
pluginspath = os.path.join(base_path, 'plugins')
for filename in os.path.join(base_name, 'plugins'):
if filename in os.listdir(pluginspath):
filename = os.path.join(pluginspath, filename)
filename = os.path.splitext(filename)[0]
self.runPlugin(filename)
def runPlugin(self, filename):
pluginName = (os.path.split(filename)[0]).split('\\')[-1]
if not pluginName.endswith("init__"):
plugin = __import__("plugins." + pluginName, fromlist=[pluginName])
clazz = plugin.getPluginClass()
obj = clazz()
self.plugins.append(obj)
def parseTest(self):
i = 0
for obj in self.plugins:
obj.parse()
obj.render()
if __name__ == '__main__':
platform = Platform(filename)
platform.parseTest()
【普通插件实现(非动态)】
目录结构:
|-main.py
|-plugins/
|-plugins/__init__.py
|-plugins/plugin1.py
|-plugins/plugin2.py
|-plugins/__init __.py
import os
import pkgutil
pkgpath = os.path.dirname(__file__)
pkgname = os.path.basename(pkgpath)
for _, file, _ in pkgutil.iter_modules([pkgpath]):
abfile = os.path.join(pkgpath, file)
__import__(pkgname+'.'+file)
|-main.py
import plugins
参考:
https://blog.csdn.net/weixin_30267691/article/details/95098184