Skip to content

📦 插件依赖管理系统

🎯 简介:MaiBot插件系统提供了强大的Python包依赖管理功能,让插件开发更加便捷和可靠。

✨ 功能概述

🎯 核心能力

  • 声明式依赖:插件可以明确声明需要的Python包
  • 智能检查:自动检查依赖包的安装状态
  • 版本控制:精确的版本要求管理
  • 可选依赖:区分必需依赖和可选依赖
  • 自动安装:可选的自动安装功能
  • 批量管理:生成统一的requirements文件
  • 安全控制:防止意外安装和版本冲突

🔄 工作流程

  1. 声明依赖 → 在插件中声明所需的Python包
  2. 加载检查 → 插件加载时自动检查依赖状态
  3. 状态报告 → 详细报告缺失或版本不匹配的依赖
  4. 智能安装 → 可选择自动安装或手动安装
  5. 运行时处理 → 插件运行时优雅处理依赖缺失

🚀 快速开始

步骤1:声明依赖

在你的插件类中添加python_dependencies字段:

python
from src.plugin_system import BasePlugin, PythonDependency, register_plugin

@register_plugin
class MyPlugin(BasePlugin):
    name = "my_plugin"
    
    # 声明Python包依赖
    python_dependencies = [
        PythonDependency(
            package_name="requests",
            version=">=2.25.0",
            description="HTTP请求库,用于网络通信"
        ),
        PythonDependency(
            package_name="numpy",
            version=">=1.20.0",
            optional=True,
            description="数值计算库(可选功能)"
        ),
    ]
    
    def get_plugin_components(self):
        # 返回插件组件
        return []

步骤2:处理依赖

在组件代码中优雅处理依赖缺失:

python
class MyAction(BaseAction):
    async def execute(self, action_input, context=None):
        try:
            import requests
            # 使用requests进行网络请求
            response = requests.get("https://api.example.com")
            return {"status": "success", "data": response.json()}
        except ImportError:
            return {
                "status": "error",
                "message": "功能不可用:缺少requests库",
                "hint": "请运行: pip install requests>=2.25.0"
            }

步骤3:检查和管理

使用依赖管理API:

python
from src.plugin_system import plugin_manager

# 检查所有插件的依赖状态
result = plugin_manager.check_all_dependencies()
print(f"检查了 {result['total_plugins_checked']} 个插件")
print(f"缺少必需依赖的插件: {result['plugins_with_missing_required']} 个")

# 生成requirements文件
plugin_manager.generate_plugin_requirements("plugin_requirements.txt")

📚 详细教程

PythonDependency 类详解

PythonDependency是依赖声明的核心类:

python
PythonDependency(
    package_name="requests",     # 导入时的包名
    version=">=2.25.0",         # 版本要求
    optional=False,             # 是否为可选依赖
    description="HTTP请求库",    # 依赖描述
    install_name=""             # pip安装时的包名(可选)
)

参数说明

参数类型必需说明
package_namestrPython导入时使用的包名(如requests
versionstr版本要求,支持pip格式(如>=1.0.0, ==2.1.3
optionalbool是否为可选依赖,默认False
descriptionstr依赖的用途描述
install_namestrpip安装时的包名,默认与package_name相同

版本格式示例

python
# 常用版本格式
PythonDependency("requests", ">=2.25.0")           # 最小版本
PythonDependency("numpy", ">=1.20.0,<2.0.0")       # 版本范围
PythonDependency("pillow", "==8.3.2")              # 精确版本
PythonDependency("scipy", ">=1.7.0,!=1.8.0")       # 排除特定版本

特殊情况处理

导入名与安装名不同的包:

python
PythonDependency(
    package_name="PIL",        # import PIL
    install_name="Pillow",     # pip install Pillow
    version=">=8.0.0"
)

可选依赖示例:

python
python_dependencies = [
    # 必需依赖 - 核心功能
    PythonDependency(
        package_name="requests",
        version=">=2.25.0",
        description="HTTP库,插件核心功能必需"
    ),
    
    # 可选依赖 - 增强功能
    PythonDependency(
        package_name="numpy",
        version=">=1.20.0",
        optional=True,
        description="数值计算库,用于高级数学运算"
    ),
    PythonDependency(
        package_name="matplotlib",
        version=">=3.0.0",
        optional=True,
        description="绘图库,用于数据可视化功能"
    ),
]

依赖检查机制

系统在以下时机会自动检查依赖:

  1. 插件加载时:检查插件声明的所有依赖
  2. 手动调用时:通过API主动检查
  3. 运行时检查:在组件执行时动态检查

检查结果状态

状态描述处理建议
no_dependencies插件未声明任何依赖无需处理
ok所有依赖都已满足正常使用
missing_optional缺少可选依赖部分功能不可用,考虑安装
missing_required缺少必需依赖插件功能受限,需要安装

🎯 最佳实践

1. 依赖声明原则

✅ 推荐做法

python
python_dependencies = [
    # 明确的版本要求
    PythonDependency(
        package_name="requests",
        version=">=2.25.0,<3.0.0",  # 主版本兼容
        description="HTTP请求库,用于API调用"
    ),
    
    # 合理的可选依赖
    PythonDependency(
        package_name="numpy",
        version=">=1.20.0",
        optional=True,
        description="数值计算库,用于数据处理功能"
    ),
]

❌ 避免的做法

python
python_dependencies = [
    # 过于宽泛的版本要求
    PythonDependency("requests"),  # 没有版本限制
    
    # 过于严格的版本要求  
    PythonDependency("numpy", "==1.21.0"),  # 精确版本过于严格
    
    # 缺少描述
    PythonDependency("matplotlib", ">=3.0.0"),  # 没有说明用途
]

2. 错误处理模式

优雅降级模式

python
class SmartAction(BaseAction):
    async def execute(self, action_input, context=None):
        # 检查可选依赖
        try:
            import numpy as np
            # 使用numpy的高级功能
            return await self._advanced_processing(action_input, np)
        except ImportError:
            # 降级到基础功能
            return await self._basic_processing(action_input)
    
    async def _advanced_processing(self, input_data, np):
        """使用numpy的高级处理"""
        result = np.array(input_data).mean()
        return {"result": result, "method": "advanced"}
    
    async def _basic_processing(self, input_data):
        """基础处理(不依赖外部库)"""
        result = sum(input_data) / len(input_data)
        return {"result": result, "method": "basic"}

🔧 使用API

检查依赖状态

python
from src.plugin_system import plugin_manager

# 检查所有插件依赖(仅检查,不安装)
result = plugin_manager.check_all_dependencies(auto_install=False)

# 检查并自动安装缺失的必需依赖
result = plugin_manager.check_all_dependencies(auto_install=True)

生成requirements文件

python
# 生成包含所有插件依赖的requirements文件
plugin_manager.generate_plugin_requirements("plugin_requirements.txt")

获取依赖状态报告

python
# 获取详细的依赖检查报告
result = plugin_manager.check_all_dependencies()
for plugin_name, status in result['plugin_status'].items():
    print(f"插件 {plugin_name}: {status['status']}")
    if status['missing']:
        print(f"  缺失必需依赖: {status['missing']}")
    if status['optional_missing']:
        print(f"  缺失可选依赖: {status['optional_missing']}")

🛡️ 安全考虑

1. 自动安装控制

  • 🛡️ 默认手动: 自动安装默认关闭,需要明确启用
  • 🔍 依赖审查: 安装前会显示将要安装的包列表
  • ⏱️ 超时控制: 安装操作有超时限制(5分钟)

2. 权限管理

  • 📁 环境隔离: 推荐在虚拟环境中使用
  • 🔒 版本锁定: 支持精确的版本控制
  • 📝 安装日志: 记录所有安装操作

📊 故障排除

常见问题

  1. 依赖检查失败

    python
    # 手动检查包是否可导入
    try:
        import package_name
        print("包可用")
    except ImportError:
        print("包不可用,需要安装")
  2. 版本冲突

    python
    # 检查已安装的包版本
    import package_name
    print(f"当前版本: {package_name.__version__}")
  3. 安装失败

    python
    # 查看安装日志
    from src.plugin_system import dependency_manager
    result = dependency_manager.get_install_summary()
    print("安装日志:", result['install_log'])
    print("失败详情:", result['failed_installs'])