diff --git a/astrbot/core/star/star_manager.py b/astrbot/core/star/star_manager.py index ff07de712..44e018dfc 100644 --- a/astrbot/core/star/star_manager.py +++ b/astrbot/core/star/star_manager.py @@ -166,7 +166,7 @@ class PluginManager: plugins.extend(_p) return plugins - def _check_plugin_dept_update(self, target_plugin: str = None): + async def _check_plugin_dept_update(self, target_plugin: str = None): """检查插件的依赖 如果 target_plugin 为 None,则检查所有插件的依赖 """ @@ -185,7 +185,7 @@ class PluginManager: pth = os.path.join(plugin_path, "requirements.txt") logger.info(f"正在安装插件 {p} 所需的依赖库: {pth}") try: - pip_installer.install(requirements_path=pth) + await pip_installer.install(requirements_path=pth) except Exception as e: logger.error(f"更新插件 {p} 的依赖失败。Code: {str(e)}") @@ -407,7 +407,7 @@ class PluginManager: module = __import__(path, fromlist=[module_str]) except (ModuleNotFoundError, ImportError): # 尝试安装依赖 - self._check_plugin_dept_update(target_plugin=root_dir_name) + await self._check_plugin_dept_update(target_plugin=root_dir_name) module = __import__(path, fromlist=[module_str]) except Exception as e: logger.error(traceback.format_exc()) diff --git a/astrbot/core/utils/pip_installer.py b/astrbot/core/utils/pip_installer.py index 0163b11b4..a7c04d3d9 100644 --- a/astrbot/core/utils/pip_installer.py +++ b/astrbot/core/utils/pip_installer.py @@ -1,5 +1,5 @@ import logging -from pip import main as pip_main +import asyncio logger = logging.getLogger("astrbot") @@ -9,7 +9,7 @@ class PipInstaller: self.pip_install_arg = pip_install_arg self.pypi_index_url = pypi_index_url - def install( + async def install( self, package_name: str = None, requirements_path: str = None, @@ -29,12 +29,29 @@ class PipInstaller: args.extend(self.pip_install_arg.split()) logger.info(f"Pip 包管理器: pip {' '.join(args)}") + try: + process = await asyncio.create_subprocess_exec( + "pip", *args, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.STDOUT, + ) - result_code = pip_main(args) + assert process.stdout is not None + async for line in process.stdout: + logger.info(line.decode().strip()) - # 清除 pip.main 导致的多余的 logging handlers - for handler in logging.root.handlers[:]: - logging.root.removeHandler(handler) + await process.wait() - if result_code != 0: - raise Exception(f"安装失败,错误码:{result_code}") + if process.returncode != 0: + raise Exception(f"安装失败,错误码:{process.returncode}") + except FileNotFoundError: + # 没有 pip + from pip import main as pip_main + result_code = await asyncio.to_thread(pip_main, args) + + # 清除 pip.main 导致的多余的 logging handlers + for handler in logging.root.handlers[:]: + logging.root.removeHandler(handler) + + if result_code != 0: + raise Exception(f"安装失败,错误码:{result_code}") diff --git a/astrbot/dashboard/routes/update.py b/astrbot/dashboard/routes/update.py index 44adf2591..f88e9a208 100644 --- a/astrbot/dashboard/routes/update.py +++ b/astrbot/dashboard/routes/update.py @@ -91,7 +91,7 @@ class UpdateRoute(Route): # pip 更新依赖 logger.info("更新依赖中...") try: - pip_installer.install(requirements_path="requirements.txt") + await pip_installer.install(requirements_path="requirements.txt") except Exception as e: logger.error(f"更新依赖失败: {e}") @@ -140,7 +140,7 @@ class UpdateRoute(Route): if not package: return Response().error("缺少参数 package 或不合法。").__dict__ try: - pip_installer.install(package, mirror=mirror) + await pip_installer.install(package, mirror=mirror) return Response().ok(None, "安装成功。").__dict__ except Exception as e: logger.error(f"/api/update_pip: {traceback.format_exc()}")