日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python所有插件框架_Python中实现简单的插件框架

發(fā)布時間:2025/3/21 python 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python所有插件框架_Python中实现简单的插件框架 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在系統(tǒng)設(shè)計中,經(jīng)常我們希望設(shè)計一套插件機制,在不修改程序主體情況下,動態(tài)去加載附能。

我設(shè)想的插件系統(tǒng):

1、通過類來實現(xiàn)

2、自動查找和導(dǎo)入

我們假設(shè)需要實現(xiàn)一個簡單的插件系統(tǒng),插件可以接收一個參數(shù)執(zhí)行。

實現(xiàn)基礎(chǔ)插件類

我們先構(gòu)建一個基礎(chǔ)插件類:plugin_collection.py

class Plugin:

"""

該基類每個插件都需要繼承,插件需要實現(xiàn)基類定義的方法"""

def __init__(self):

self.description = '未知'

def perform_operation(self, argument):

"""

實際執(zhí)行插件所執(zhí)行的方法,該方法所有插件類都需要實現(xiàn)

"""

raise NotImplementedError

所有的插件類需要申明description來進行插件描述,并且要實現(xiàn)perform_operation方法,該方法是實際加載插件將去執(zhí)行的方法。

簡易插件

我們現(xiàn)在實現(xiàn)一個插件,實際執(zhí)行時僅返回傳入的參數(shù): plugins/identity.py

import plugin_collection

class Identity(plugin_collection.Plugin):

"""

This plugin is just the identity function: it returns the argument

"""

def __init__(self):

super().__init__()

self.description = 'Identity function'

def perform_operation(self, argument):

"""

The actual implementation of the identity plugin is to just return the

argument

"""

return argument

動態(tài)加載機制

因為我們預(yù)實現(xiàn)動態(tài)加載插件。我們通過定義一個PluginCollection來完成該職責(zé),它將載入所有的插件,并且根據(jù)傳入的值執(zhí)行perform_operation方法。PluginCollection類基礎(chǔ)組件實現(xiàn)如下:plugins_collection.py

class PluginCollection:

"""

該類會通過傳入的package查找繼承了Plugin類的插件類

"""

def __init__(self, plugin_package):

self.plugin_package = plugin_package

self.reload_plugins()

def reload_plugins(self):

"""

重置plugins列表,遍歷傳入的package查詢有效的插件

"""

self.plugins = []

self.seen_paths = []

print()

print(f"在 {self.plugin_package} 包里查找插件")

self.walk_package(self.plugin_package)

def apply_all_plugins_on_value(self, argument):

print()

print(f"執(zhí)行參數(shù) {argument} 到所有的插件:")

for plugin in self.plugins:

print(f" 執(zhí)行 {plugin.description} 參數(shù) {argument} 結(jié)果 {plugin.perform_operation(argument)}")

最關(guān)鍵的是PluginCollection類里的walk_package方法,該方法按如下步驟操作:

1、操作package里所有的模塊

2、針對找到的模塊,檢查是否是Plugin的子類,非Plugin自身。每個插件將會初始化并加入到列表。該檢查的好處是你可以放入其他Python模塊,也并不影響插件的使用

3、檢查當(dāng)前package下的子目錄,遞歸查找插件

def walk_package(self, package):

"""

遞歸遍歷包里獲取所有的插件

"""

imported_package = __import__(package, fromlist=['blah'])

for _, pluginname, ispkg in pkgutil.iter_modules(imported_package.__path__, imported_package.__name__ + '.'):

if not ispkg:

plugin_module = __import__(pluginname, fromlist=['blah'])

clsmembers = inspect.getmembers(plugin_module, inspect.isclass)

for (_, c) in clsmembers:

# 僅加入Plugin類的子類,忽略掉Plugin本身

if issubclass(c, Plugin) and (c is not Plugin):

print(f' 找到插件類: {c.__module__}.{c.__name__}')

self.plugins.append(c())

# 現(xiàn)在我們已經(jīng)查找了當(dāng)前package中的所有模塊,現(xiàn)在我們遞歸查找子packages里的附件模塊

all_current_paths = []

if isinstance(imported_package.__path__, str):

all_current_paths.append(imported_package.__path__)

else:

all_current_paths.extend([x for x in imported_package.__path__])

for pkg_path in all_current_paths:

if pkg_path not in self.seen_paths:

self.seen_paths.append(pkg_path)

# 獲取當(dāng)前package中的子目錄

child_pkgs = [p for p in os.listdir(pkg_path) if os.path.isdir(os.path.join(pkg_path, p))]

# 遞歸遍歷子目錄的package

for child_pkg in child_pkgs:

self.walk_package(package + '.' + child_pkg)

測試

現(xiàn)在我們寫個簡單的測試:test.py

from plugin_collection import PluginCollection

my_plugins = PluginCollection('plugins')

my_plugins.apply_all_plugins_on_value(5)

執(zhí)行結(jié)果:

$ python3 test.py

在 plugins 包里查找插件

找到插件類: plugins.identity.Identity

執(zhí)行參數(shù) 5 到所有的插件:

執(zhí)行 Identity function 參數(shù) 5 結(jié)果 5

總結(jié)

以上是生活随笔為你收集整理的python所有插件框架_Python中实现简单的插件框架的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。