
包管理器开发工具【免费下载链接】pipThe Python package installer项目地址https://gitcode.com/gh_mirrors/pi/pip点击查看免费下载导读本篇文章围绕 pip 的一个性能优化特性展开在安装带有console_scripts入口点的 wheel 时pip 不再对PATH环境变量中的每一条目执行路径解析resolve而是先通过字符串匹配快速排除绝大多数目录从而显著降低安装耗时。该特性记录于仓库 news 目录的特性更新条目 news/14235.feature.rst其完整实现位于src/pip/_internal/operations/install/wheel.py的message_about_scripts_not_on_PATH函数中。读完本文你将理解这一优化背后的调用链、判定算法、对应的单元测试以及--no-warn-script-location选项的实际用法。背景为什么“脚本不在 PATH 上”警告会成为性能瓶颈pip 在安装一个 wheel 后如果该 wheel 声明了console_scripts入口点例如[project.scripts]或旧式setup.py中的entry_points{console_scripts: ...}就会在该环境的 bin 目录生成对应的可执行启动脚本。随后 pip 会检查这些脚本所在的目录是否位于PATH中若不在则给出警告The script foo is installed in /path/to/bin which is not on PATH. Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.这个检查本身看似简单但存在一个隐蔽的性能陷阱判断“目录是否在 PATH 上”需要将 PATH 中的每个条目与脚本安装目录进行等价比较。由于PATH条目常常以相对路径、含..、.、重复分隔符或~等形式出现单纯做字符串比较可能漏判因此过去需要调用Path.resolve()对每一条PATH 条目做完整的文件系统解析解析符号链接、规范化路径等。在 PATH 条目很多、目录层级很深或文件系统较慢的环境里这一步会产生大量系统调用拖慢整个安装流程。news 条目 news/14235.feature.rst 所描述的改进正是针对这一热点仅在必要的时候才去 resolve PATH 条目。优化核心message_about_scripts_not_on_PATH的实现该特性的实现集中在 src/pip/_internal/operations/install/wheel.py#L120-L193 的message_about_scripts_not_on_PATH函数。其算法可以概括为“两阶段过滤”字符串匹配快筛先从环境变量中读取PATH并按os.pathsep切分为条目wheel.py#L139然后以脚本安装目录的规范化字符串直接与 PATH 条目比对只有不匹配的目录才进入候选集。仅对剩余候选做 resolve源码注释明确指出“Resolving PATH entries can be slow, so only do it for whats left.”wheel.py#L148-L155即只有通过字符串比较仍然无法确认的目录才调用Path.resolve()做精确判定。下面是关键代码段的逻辑拆解# 1. 将脚本按安装目录分组 grouped_by_dir: dict[Path, set[str]] collections.defaultdict(set) for destfile in scripts: dest_path Path(destfile) parent_dir dest_path.parent.resolve() grouped_by_dir[parent_dir].add(dest_path.name) # 2. 与 sys.executable 所在目录、PATH 条目做字符串匹配快速剔除 path_entries os.environ.get(PATH, ).split(os.pathsep) warn_for { parent_dir: scripts for parent_dir, scripts in grouped_by_dir.items() if parent_dir ! executable_dir and str(parent_dir) not in path_entries } # 3. 只剩下未确认的目录才走昂贵的 resolve if warn_for: not_warn_dirs {Path(i).resolve() for i in path_entries} warn_for { parent_dir: scripts for parent_dir, scripts in warn_for.items() if parent_dir not in not_warn_dirs }该函数还处理了几个边界细节空脚本集合直接返回None不产生任何警告wheel.py#L125-L126。排除sys.executable目录当可执行文件与sys.executable同目录时例如未激活 venv 却直接调用 venv 内 Python 的场景不告警wheel.py#L136-L138。~开头条目提示若 PATH 中存在以~开头的条目会附加一条说明“当前 PATH 包含以~开头的路径部分应用可能不会展开它”wheel.py#L183-L190。多脚本多目录的文案按目录分别生成句子并用--no-warn-script-location作为统一的消警提示wheel.py#L159-L181。PATH 缺失与空串等价PATH环境变量缺失时按空字符串处理二者行为一致由测试 tests/unit/test_wheel.py#L595-L606 验证。调用链从安装命令到警告输出message_about_scripts_not_on_PATH并不是孤立函数它处于一条完整的调用链中参数一路从 CLI 传递到安装逻辑命令行选项定义src/pip/_internal/commands/install.py#L311-L317 注册了--no-warn-script-locationactionstore_false、destwarn_script_location、默认True。命令层解析后传入安装命令把options.warn_script_location一路传给安装过程install.py#L545-L561。中间传递req_install.py、req/__init__.py与operations/install/wheel.py均以参数形式透传该布尔值src/pip/_internal/req/req_install.py#L769、src/pip/_internal/req/init.py#L43。最终判定在 wheel 安装完成后若warn_script_location为真则对生成的 console scripts 调用检查函数并输出告警日志wheel.py#L681-L684。值得注意的是构建环境build environment在安装构建依赖时主动关闭了该检查warn_script_locationFalse见 src/pip/_internal/build_env/installer.py#L297因为临时构建环境中的脚本目录本就不在用户 PATH 上检查既无意义又会拖慢构建。此外get_console_scripts还负责将 wheel 元数据中的入口点分组为console_scripts与gui_scripts两类wheel.py#L109-L117GUI 脚本同样会被生成但不参与PATH 检查——检查对象仅限generated_console_scriptswheel.py#L676-L684。单元测试如何验证优化生效tests/unit/test_wheel.py中以TestScriptsWarning测试类tests/unit/test_wheel.py#L483-L485 附近的_template辅助方法系统性地覆盖了该函数的行为。其中最值得关注的是直接验证“按需 resolve”的测试 test_PATH_entries_are_not_resolved_when_a_string_match_settles_itdef test_PATH_entries_are_not_resolved_when_a_string_match_settles_it( self, monkeypatch: pytest.MonkeyPatch, tmp_path: Path ) - None: ... def recording_resolve(self: Path, strict: bool False) - Path: resolved.append(str(self)) return unpatched_resolve(self, strict) monkeypatch.setattr(Path, resolve, recording_resolve) retval self._template( paths[str(scripts_dir), str(unrelated_entry)], scripts[str(scripts_dir / foo)], ) assert retval is None assert str(unrelated_entry) not in resolved该测试通过 monkeypatch 包裹Path.resolve记录所有实际发生的 resolve 调用然后断言当脚本目录在字符串层面已经匹配上某个 PATH 条目时其他未涉及的 PATH 条目不会被 resolve——这正是本条 news 所述优化的直接行为证据。其余测试还覆盖了单/多脚本在单/多目录下均不在 PATH 时的告警文案tests/unit/test_wheel.py#L491-L527目录确实在 PATH 上时不产生警告tests/unit/test_wheel.py#L529-L546路径规范化如/a/./b/../b//c/与/a/b/c等价test_PATH_check_path_normalizationWindows 上大小写不敏感匹配test_PATH_check_case_insensitive_on_windows尾部路径分隔符的处理test_trailing_ossep_removal。实用配置如何关闭该警告如果你不希望 pip 每次都在 PATH 之外安装脚本时提示有两种标准做法命令行方式安装时附加--no-warn-script-locationpython -m pip install --no-warn-script-location package配置文件方式在 pip 配置中设置no-warn-script-location true。pip 的配置文档 docs/html/topics/configuration.md#L175-L184 明确将--no-warn-script-location列为可用no-前缀布尔选项对应配置项写法为no-warn-script-location true布尔选项在配置文件中带no-前缀时启用该行为。小结关注点结论优化目标避免在安装 wheel 时为每个脚本路径解析全部 PATH 条目核心实现src/pip/_internal/operations/install/wheel.py#L120-L193message_about_scripts_not_on_PATH核心策略先字符串匹配快速过滤仅对剩余候选做Path.resolve()行为验证tests/unit/test_wheel.py#L572-L593 断言未匹配条目不被 resolve关闭方式CLI--no-warn-script-location或配置no-warn-script-location true适用场景PATH 条目多、目录解析慢的 CI、容器与常规本地安装环境这一改动保持了告警行为的完全一致只是把昂贵的文件系统解析推迟到“非做不可”的时刻属于典型的“以少量代码换取可观安装提速”的工程优化。赞分享包管理器开发工具【免费下载链接】pipThe Python package installer项目地址https://gitcode.com/gh_mirrors/pi/pip点击查看免费下载相关推荐如何在 NVIDIA GPU 上用 pip、uv 或 Docker 安装 SGLang 并启动第一个推理服务如何在 NVIDIA GPU 上用 pip、uv 或 Docker 安装 SGLang 并启动第一个推理服务 SGLang 是一个面向大语言模型和多模态模型的推包管理器开发工具极速条件加载yepnope.js脚本加载器全解析极速条件加载yepnope.js脚本加载器全解析 你还在为前端资源加载烦恼吗 当用户访问你的网站时是否遇到过因脚本加载阻塞导致的页面卡顿是否还在手动判断mcp-use Python SDK 路线图解析从 100% 协议合规到 SDK 2.0 架构重构mcp use Python SDK 路线图解析从 100% 协议合规到 SDK 2.0 架构重构 mcp use 是一套覆盖 MCP 客户端、服务端与 Ag后端MCP 服务MCP ClientsAI Agent人工智能上一篇3分钟免费实现Figma中文界面设计师必备的完整汉化指南下一篇Chrome图片格式转换终极教程一键保存为PNG/JPG/WebP的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考