Python 插件实现(动态加载与静态加载)

【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

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Python爬虫在处理JavaScript动态加载的网页时,可以使用Selenium库和webdriver来模拟浏览器的行为,从网页中读取数据。这样才能找到动态加载的标签。 通过使用Selenium,可以驱动浏览器打开网页,并渲染网页中的JavaScript代码,从而获取动态加载的内容。 对于动态加载的标签,可以通过查看网页源码或者使用开发者工具来确定其所在的位置和属性。例如,在一个动态加载的网页中,可以使用Selenium的定位方法,如XPath或CSS选择器,来定位特定的标签。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Python爬虫进阶——爬取数据js动态加载的网页](https://blog.csdn.net/zhiyan6415/article/details/116270310)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Python爬虫遇上动态加载](https://blog.csdn.net/Itsme_MrJJ/article/details/126033892)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值