1- """pip 依赖安装辅助 — 插件/模块共用
2-
3- 设计目标 (对齐 nonebot 的"框架自装依赖", 且不挑环境):
4- · 用 `sys.executable -m pip` 安装 → 天然装进"当前跑 bot 的这个 Python", 虚拟环境里也对;
5- · site-packages 不可写时 (无 root / venv 属主为 root), 自动 `--target` 装到可写的
6- .pydeps 目录并注入 sys.path, 无需 root, venv 内外均适用;
7- · 多镜像兜底 (配置源失败自动换官方源重试);
8- · pip 跑在独立单线程池里, 与事件循环 / DNS / Web 隔离, 装依赖不阻塞收发消息。
9- """
1+ """pip 依赖安装辅助 — 插件/模块共用, 自动适配环境并多镜像兜底"""
102
113import asyncio
124import contextlib
2416
2517log = get_logger (FRAMEWORK , '依赖安装' )
2618
27- # 当运行 bot 的 Python 环境 site-packages 不可写时 (无 root / venv 属主为 root, pip 报
28- # Errno 13 Permission denied), 依赖改装到这个可写目录并注入 sys.path: 免 root、
29- # venv 内外都能让插件 import 到 (venv 里 --user 会被 pip 拒绝, 故用 --target)。
19+ # site-packages 不可写时, 依赖 --target 装到此可写目录并注入 sys.path
3020_ROOT_DIR = os .path .dirname (os .path .dirname (os .path .dirname (os .path .abspath (__file__ ))))
3121_DEPS_DIR = os .path .join (_ROOT_DIR , '.pydeps' )
3222
@@ -40,8 +30,7 @@ def _ensure_deps_dir_on_path():
4030if os .path .isdir (_DEPS_DIR ):
4131 _ensure_deps_dir_on_path ()
4232
43- # 独立单线程池: pip 是重 IO/CPU 的阻塞操作, 放这里跑绝不占用 asyncio 默认执行器
44- # (默认执行器还兼着 DNS 解析、Web/统计查询等, 被 pip 占满会连带卡住整个面板)。
33+ # 独立单线程池: pip 阻塞操作不占用 asyncio 默认执行器
4534_EXECUTOR = None
4635_EXECUTOR_LOCK = threading .Lock ()
4736
@@ -153,11 +142,7 @@ def all_requirements_met(req_path):
153142
154143
155144def _mirror_attempts ():
156- """返回按优先级排列的镜像参数列表; '' 表示官方源 (不带 -i)。
157-
158- 支持 settings.pip.mirrors (列表) 做多镜像兜底; 否则用 settings.pip.mirror
159- (单个), 并追加官方源兜底。
160- """
145+ """返回按优先级排列的镜像参数列表, '' 表示官方源"""
161146 mirrors = cfg .get ('settings' , 'pip.mirrors' , None )
162147 if isinstance (mirrors , (list , tuple )) and mirrors :
163148 seq = [str (m ).strip () for m in mirrors if str (m ).strip ()]
0 commit comments