|
3 | 3 | import importlib.util |
4 | 4 | import inspect |
5 | 5 | import os |
| 6 | +import sys |
6 | 7 | import time |
7 | 8 | import traceback |
8 | 9 | from concurrent.futures import ThreadPoolExecutor, as_completed |
@@ -198,10 +199,14 @@ def stop(self, pid: Optional[str] = None): |
198 | 199 | # 清空指定插件 |
199 | 200 | self._plugins.pop(pid, None) |
200 | 201 | self._running_plugins.pop(pid, None) |
| 202 | + # 清除插件模块缓存,包括所有子模块 |
| 203 | + self._clear_plugin_modules(pid) |
201 | 204 | else: |
202 | 205 | # 清空 |
203 | 206 | self._plugins = {} |
204 | 207 | self._running_plugins = {} |
| 208 | + # 清除所有插件模块缓存 |
| 209 | + self._clear_plugin_modules() |
205 | 210 | logger.info("插件停止完成") |
206 | 211 |
|
207 | 212 | @staticmethod |
@@ -366,25 +371,51 @@ def remove_plugin(self, plugin_id: str): |
366 | 371 | """ |
367 | 372 | self.stop(plugin_id) |
368 | 373 |
|
369 | | - # 从模块列表中移除插件 |
370 | | - from sys import modules |
371 | | - try: |
372 | | - del modules[f"app.plugins.{plugin_id.lower()}"] |
373 | | - except KeyError: |
374 | | - pass |
375 | | - |
376 | 374 | def reload_plugin(self, plugin_id: str): |
377 | 375 | """ |
378 | 376 | 将一个插件重新加载到内存 |
379 | 377 | :param plugin_id: 插件ID |
380 | 378 | """ |
381 | | - # 先移除 |
| 379 | + # 先移除插件实例 |
382 | 380 | self.stop(plugin_id) |
383 | 381 | # 重新加载 |
384 | 382 | self.start(plugin_id) |
385 | 383 | # 广播事件 |
386 | 384 | eventmanager.send_event(EventType.PluginReload, data={"plugin_id": plugin_id}) |
387 | 385 |
|
| 386 | + @staticmethod |
| 387 | + def _clear_plugin_modules(plugin_id: Optional[str] = None): |
| 388 | + """ |
| 389 | + 清除插件及其所有子模块的缓存 |
| 390 | + :param plugin_id: 插件ID |
| 391 | + """ |
| 392 | + |
| 393 | + # 构建插件模块前缀 |
| 394 | + if plugin_id: |
| 395 | + plugin_module_prefix = f"app.plugins.{plugin_id.lower()}" |
| 396 | + else: |
| 397 | + plugin_module_prefix = "app.plugins" |
| 398 | + |
| 399 | + # 收集需要删除的模块名(创建模块名列表的副本以避免迭代时修改字典) |
| 400 | + modules_to_remove = [] |
| 401 | + for module_name in list(sys.modules.keys()): |
| 402 | + if module_name == plugin_module_prefix or module_name.startswith(plugin_module_prefix + "."): |
| 403 | + modules_to_remove.append(module_name) |
| 404 | + |
| 405 | + # 删除模块 |
| 406 | + for module_name in modules_to_remove: |
| 407 | + try: |
| 408 | + del sys.modules[module_name] |
| 409 | + logger.debug(f"已清除插件模块缓存:{module_name}") |
| 410 | + except KeyError: |
| 411 | + # 模块可能已经被删除 |
| 412 | + pass |
| 413 | + |
| 414 | + if modules_to_remove: |
| 415 | + logger.info(f"插件 {plugin_id} 共清除 {len(modules_to_remove)} 个模块缓存:{modules_to_remove}") |
| 416 | + else: |
| 417 | + logger.debug(f"插件 {plugin_id} 没有找到需要清除的模块缓存") |
| 418 | + |
388 | 419 | def sync(self) -> List[str]: |
389 | 420 | """ |
390 | 421 | 安装本地不存在或需要更新的插件 |
@@ -1416,8 +1447,9 @@ def _modify_federation_files(self, dist_dir: Path, original_class_name: str, |
1416 | 1447 | content = f.read() |
1417 | 1448 |
|
1418 | 1449 | # 替换CSS中可能的类名引用 |
1419 | | - content = content.replace(original_class_name.lower(), clone_class_name.lower()) |
1420 | | - content = content.replace(original_class_name, clone_class_name) |
| 1450 | + content = content.replace(original_class_name.lower(), |
| 1451 | + clone_class_name.lower()).replace(original_class_name, |
| 1452 | + clone_class_name) |
1421 | 1453 |
|
1422 | 1454 | with open(file_path, 'w', encoding='utf-8') as f: |
1423 | 1455 | f.write(content) |
|
0 commit comments