调整插件加载逻辑

This commit is contained in:
liuwei
2025-03-19 10:20:22 +08:00
parent feb14b16f6
commit 9e42a4690d
5 changed files with 125 additions and 86 deletions

View File

@@ -1,5 +1,6 @@
import importlib import importlib
import inspect import inspect
import logging
import os import os
import sys import sys
from typing import Dict, List, Any, Optional, Type from typing import Dict, List, Any, Optional, Type
@@ -26,6 +27,7 @@ class PluginManager:
self.plugin_modules = {} # 插件模块字典 self.plugin_modules = {} # 插件模块字典
self.system_context = {} # 系统上下文 self.system_context = {} # 系统上下文
self.LOG = logging.getLogger(__name__)
# 确保插件目录存在 # 确保插件目录存在
if not os.path.exists(self.plugin_dir): if not os.path.exists(self.plugin_dir):
os.makedirs(self.plugin_dir) os.makedirs(self.plugin_dir)
@@ -61,7 +63,7 @@ class PluginManager:
elif item.endswith(".py") and not item.startswith("__"): elif item.endswith(".py") and not item.startswith("__"):
# 单文件插件 # 单文件插件
plugin_modules.append(item[:-3]) plugin_modules.append(item[:-3])
self.LOG.info(f"plugin_modules:{plugin_modules}")
return plugin_modules return plugin_modules
def load_plugin(self, plugin_name: str) -> Optional[PluginInterface]: def load_plugin(self, plugin_name: str) -> Optional[PluginInterface]:
@@ -83,20 +85,18 @@ class PluginManager:
if os.path.isdir(os.path.join(self.plugin_dir, plugin_name)): if os.path.isdir(os.path.join(self.plugin_dir, plugin_name)):
plugin_path = os.path.join(self.plugin_dir, plugin_name) plugin_path = os.path.join(self.plugin_dir, plugin_name)
# 优先从main.py加载插件 # 直接从main.py加载插件不再尝试从__init__.py加载
main_module_path = f"{plugin_name}.main" main_module_path = f"{plugin_name}.main"
if os.path.exists(os.path.join(plugin_path, "main.py")): if os.path.exists(os.path.join(plugin_path, "main.py")):
try: try:
module = importlib.import_module(main_module_path) module = importlib.import_module(main_module_path)
self.plugin_modules[plugin_name] = module self.plugin_modules[plugin_name] = module
except ImportError: except ImportError as e:
# 如果main.py导入失败尝试从__init__.py加载 self.LOG.error(f"导入插件模块 {main_module_path} 失败: {e}")
module = importlib.import_module(plugin_name) return None
self.plugin_modules[plugin_name] = module
else: else:
# 如果没有main.py从__init__.py加载 self.LOG.error(f"插件 {plugin_name} 缺少 main.py 文件")
module = importlib.import_module(plugin_name) return None
self.plugin_modules[plugin_name] = module
else: else:
# 单文件插件 # 单文件插件
plugin_path = self.plugin_dir plugin_path = self.plugin_dir
@@ -107,17 +107,46 @@ class PluginManager:
plugin_class = None plugin_class = None
for name, obj in inspect.getmembers(module): for name, obj in inspect.getmembers(module):
if (inspect.isclass(obj) and if (inspect.isclass(obj) and
issubclass(obj, PluginInterface) and issubclass(obj, PluginInterface) and
obj != PluginInterface obj != PluginInterface and
# 修改这里:不排除继承自 MessagePluginInterface 和 ScheduledPluginInterface 的类 obj != MessagePluginInterface and
# obj != MessagePluginInterface and obj != ScheduledPluginInterface):
# obj != ScheduledPluginInterface
):
plugin_class = obj plugin_class = obj
break break
# 如果插件类为空尝试查找get_plugin函数
if plugin_class is None: if plugin_class is None:
print(f"插件 {plugin_name} 中未找到有效的插件类") get_plugin_func = getattr(module, "get_plugin", None)
if callable(get_plugin_func):
plugin = get_plugin_func()
if isinstance(plugin, PluginInterface):
# 设置插件路径
plugin.set_plugin_path(plugin_path)
# 加载插件配置
if not plugin.load_config():
self.LOG.error(f"插件 {plugin_name} 加载配置失败")
return None
# 初始化插件
if not plugin.initialize(self.system_context):
self.LOG.error(f"插件 {plugin_name} 初始化失败")
return None
# 注册插件
PluginRegistry().register(plugin)
# 存储插件实例
self.plugins[plugin.name] = plugin
# 发布插件加载事件
EventSystem().publish(EventType.PLUGIN_LOADED, {"plugin": plugin})
return plugin
else:
self.LOG.error(f"插件 {plugin_name} 的 get_plugin() 返回的不是有效的插件实例")
else:
self.LOG.error(f"插件 {plugin_name} 中未找到有效的插件类或 get_plugin 函数")
return None return None
# 实例化插件 # 实例化插件
@@ -129,12 +158,12 @@ class PluginManager:
# 加载插件配置 # 加载插件配置
if not plugin.load_config(): if not plugin.load_config():
print(f"插件 {plugin_name} 加载配置失败") self.LOG.error(f"插件 {plugin_name} 加载配置失败")
return None return None
# 初始化插件 # 初始化插件
if not plugin.initialize(self.system_context): if not plugin.initialize(self.system_context):
print(f"插件 {plugin_name} 初始化失败") self.LOG.error(f"插件 {plugin_name} 初始化失败")
return None return None
# 注册插件 # 注册插件
@@ -149,7 +178,7 @@ class PluginManager:
return plugin return plugin
except Exception as e: except Exception as e:
print(f"加载插件 {plugin_name} 失败: {e}") self.LOG.error(f"加载插件 {plugin_name} 失败: {e}")
return None return None
def load_all_plugins(self) -> Dict[str, PluginInterface]: def load_all_plugins(self) -> Dict[str, PluginInterface]:
@@ -177,7 +206,7 @@ class PluginManager:
卸载是否成功 卸载是否成功
""" """
if plugin_name not in self.plugins: if plugin_name not in self.plugins:
print(f"插件 {plugin_name} 未加载") self.LOG.info(f"插件 {plugin_name} 未加载")
return False return False
plugin = self.plugins[plugin_name] plugin = self.plugins[plugin_name]
@@ -185,12 +214,12 @@ class PluginManager:
# 停止插件 # 停止插件
if plugin.status == PluginStatus.RUNNING: if plugin.status == PluginStatus.RUNNING:
if not plugin.stop(): if not plugin.stop():
print(f"停止插件 {plugin_name} 失败") self.LOG.info(f"停止插件 {plugin_name} 失败")
return False return False
# 清理插件资源 # 清理插件资源
if not plugin.cleanup(): if not plugin.cleanup():
print(f"清理插件 {plugin_name} 资源失败") self.LOG.info(f"清理插件 {plugin_name} 资源失败")
return False return False
# 注销插件 # 注销插件
@@ -215,13 +244,13 @@ class PluginManager:
启动是否成功 启动是否成功
""" """
if plugin_name not in self.plugins: if plugin_name not in self.plugins:
print(f"插件 {plugin_name} 未加载") self.LOG.info(f"插件 {plugin_name} 未加载")
return False return False
plugin = self.plugins[plugin_name] plugin = self.plugins[plugin_name]
if plugin.status == PluginStatus.RUNNING: if plugin.status == PluginStatus.RUNNING:
print(f"插件 {plugin_name} 已经在运行") self.LOG.info(f"插件 {plugin_name} 已经在运行")
return True return True
if plugin.start(): if plugin.start():
@@ -242,13 +271,13 @@ class PluginManager:
停止是否成功 停止是否成功
""" """
if plugin_name not in self.plugins: if plugin_name not in self.plugins:
print(f"插件 {plugin_name} 未加载") self.LOG.info(f"插件 {plugin_name} 未加载")
return False return False
plugin = self.plugins[plugin_name] plugin = self.plugins[plugin_name]
if plugin.status != PluginStatus.RUNNING: if plugin.status != PluginStatus.RUNNING:
print(f"插件 {plugin_name} 未在运行") self.LOG.info(f"插件 {plugin_name} 未在运行")
return True return True
if plugin.stop(): if plugin.stop():
@@ -271,7 +300,7 @@ class PluginManager:
# 卸载插件 # 卸载插件
if plugin_name in self.plugins: if plugin_name in self.plugins:
if not self.unload_plugin(plugin_name): if not self.unload_plugin(plugin_name):
print(f"卸载插件 {plugin_name} 失败") self.LOG.info(f"卸载插件 {plugin_name} 失败")
return None return None
# 重新导入模块 # 重新导入模块
@@ -279,7 +308,7 @@ class PluginManager:
try: try:
importlib.reload(self.plugin_modules[plugin_name]) importlib.reload(self.plugin_modules[plugin_name])
except Exception as e: except Exception as e:
print(f"重新导入插件模块 {plugin_name} 失败: {e}") self.LOG.info(f"重新导入插件模块 {plugin_name} 失败: {e}")
return None return None
# 加载插件 # 加载插件

View File

@@ -1,7 +0,0 @@
from plugins.message_summary.main import MessageSummaryPlugin
def get_plugin():
"""获取插件实例"""
return MessageSummaryPlugin()
__all__ = ['MessageSummaryPlugin', 'get_plugin']

View File

@@ -1,7 +0,0 @@
from plugins.stats_collector.main import StatsCollectorPlugin
def get_plugin():
"""获取插件实例"""
return StatsCollectorPlugin()
__all__ = ['StatsCollectorPlugin', 'get_plugin']

View File

@@ -3,7 +3,7 @@ import time
from typing import Dict, Any, Tuple, Optional, List from typing import Dict, Any, Tuple, Optional, List
from datetime import datetime from datetime import datetime
from plugin_common.plugin_interface import PluginInterface from plugin_common.plugin_interface import PluginInterface, PluginStatus
from event_system.event_manager import EventManager from event_system.event_manager import EventManager
# 使用正确的事件类型导入 # 使用正确的事件类型导入
from event_system.events.plugin_events import PluginCallStartEvent, PluginCallEndEvent, PluginCallErrorEvent from event_system.events.plugin_events import PluginCallStartEvent, PluginCallEndEvent, PluginCallErrorEvent
@@ -154,3 +154,15 @@ class StatsCollectorPlugin(PluginInterface):
self.event_manager.unregister(PluginCallErrorEvent, self.handle_plugin_error) self.event_manager.unregister(PluginCallErrorEvent, self.handle_plugin_error)
self.logger.info("统计收集插件已关闭") self.logger.info("统计收集插件已关闭")
def start(self) -> bool:
"""启动插件"""
self.status = PluginStatus.RUNNING
self.LOG.info(f"{self.name} 插件已启动")
return True
def stop(self) -> bool:
"""停止插件"""
self.status = PluginStatus.STOPPED
self.LOG.info(f"{self.name} 插件已停止")
return True

View File

@@ -2,7 +2,7 @@ import logging
import threading import threading
from typing import Dict, Any, Tuple, Optional, List from typing import Dict, Any, Tuple, Optional, List
from plugin_common.plugin_interface import PluginInterface from plugin_common.plugin_interface import PluginInterface, PluginStatus
from .dashboard_server import DashboardServer from .dashboard_server import DashboardServer
@@ -144,3 +144,15 @@ class StatsDashboardPlugin(PluginInterface):
"""关闭插件""" """关闭插件"""
if self.server: if self.server:
self.stop_server() self.stop_server()
def start(self) -> bool:
"""启动插件"""
self.status = PluginStatus.RUNNING
self.LOG.info(f"{self.name} 插件已启动")
return True
def stop(self) -> bool:
"""停止插件"""
self.status = PluginStatus.STOPPED
self.LOG.info(f"{self.name} 插件已停止")
return True