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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

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

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

在系統設計中,經常我們希望設計一套插件機制,在不修改程序主體情況下,動態去加載附能。

我設想的插件系統:

1、通過類來實現

2、自動查找和導入

我們假設需要實現一個簡單的插件系統,插件可以接收一個參數執行。

實現基礎插件類

我們先構建一個基礎插件類:plugin_collection.py

class Plugin:

"""

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

def __init__(self):

self.description = '未知'

def perform_operation(self, argument):

"""

實際執行插件所執行的方法,該方法所有插件類都需要實現

"""

raise NotImplementedError

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

簡易插件

我們現在實現一個插件,實際執行時僅返回傳入的參數: 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

動態加載機制

因為我們預實現動態加載插件。我們通過定義一個PluginCollection來完成該職責,它將載入所有的插件,并且根據傳入的值執行perform_operation方法。PluginCollection類基礎組件實現如下: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"執行參數 {argument} 到所有的插件:")

for plugin in self.plugins:

print(f" 執行 {plugin.description} 參數 {argument} 結果 {plugin.perform_operation(argument)}")

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

1、操作package里所有的模塊

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

3、檢查當前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())

# 現在我們已經查找了當前package中的所有模塊,現在我們遞歸查找子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)

# 獲取當前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)

測試

現在我們寫個簡單的測試:test.py

from plugin_collection import PluginCollection

my_plugins = PluginCollection('plugins')

my_plugins.apply_all_plugins_on_value(5)

執行結果:

$ python3 test.py

在 plugins 包里查找插件

找到插件類: plugins.identity.Identity

執行參數 5 到所有的插件:

執行 Identity function 參數 5 結果 5

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。