尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

conda 内置 Windows Launcher 兼容机制解析:从 cli-32.exe/cli-64.exe 到 conda-launchers 包的演进

发布时间:2026/9/16 12:14:43

资讯中心
01
ARTICLE

conda 内置 Windows Launcher 兼容机制解析:从 cli-32.exe/cli-64.exe 到 conda-launchers 包的演进

conda 内置 Windows Launcher 兼容机制解析:从 cli-32.exe/cli-64.exe 到 conda-launchers 包的演进
conda 内置 Windows Launcher 兼容机制解析从 cli-32.exe/cli-64.exe 到 conda-launchers 包的演进【免费下载链接】condaA system-level, binary package and environment manager running on all major operating systems and platforms.项目地址: https://gitcode.com/GitHub_Trending/co/condaconda 的 Windows 入口点entry point在 Windows 上以.exe可执行文件形式存在本文围绕 conda/shell/README.md 中记录的cli-32.exe与cli-64.exe两个内置 stub 启动器剖析它们在 conda 从「自带 stub」过渡到「使用独立conda-launchers包」过程中的兼容性角色、源码级实现原理与移除约束。读完本文你将理解 conda 在 Windows 上创建入口点 .exe 的完整选择链路含自升级场景的时序问题掌握conda-launchers的查找、哈希校验与回退逻辑以及为何这两个内置文件至今没有明确的移除时间表。背景为什么 conda/shell 下躺着两个 Windows 可执行文件在 Windows 平台conda 创建 Python 包入口点如conda.exe、pip.exe时并不是直接复制 Python 脚本而是复制一个「启动器 stub」可执行文件它负责定位解释器并启动对应的 Python 模块。过去conda 依赖安装在Scripts/conda.exe的自身副本而从 conda 26.3.0 开始见 CHANGELOG.md 中收录的 PR #15678conda 改为使用内置的 Windows stub 可执行文件来创建入口点并引入平台到 stub 的映射。当前 conda/shell/ 目录中保留了两个文件文件角色conda/shell/cli-64.exe64 位 Windows 入口点 stubconda/shell/cli-32.exe32 位 Windows 入口点 stub回退用其余如 conda/shell/condabin/conda.bat、conda/shell/etc/profile.d/conda.sh 等则是激活/反激活脚本与本文讨论的入口点 stub 属于不同机制不在此展开。需要说明的是这两个文件仅是「为兼容性保留」的过渡产物。conda 现在优先使用独立的conda-launchers包recipe/meta.yaml中以conda-launchers 24.7.1 # [win]声明为 Windows 运行时依赖来提供入口点详见后文。cli-64.exe自升级事务的「安全垫」conda/shell/README.md 明确指出包括 26.7.2 在内的已发布 conda 客户端在创建 Windows 入口点时仍会复制cli-64.exe。这里的关键在于自升级self-upgrade的时序问题用户运行conda update conda触发对 conda 自身的更新事务事务会替换 conda 的包文件包括旧的启动器文件但正在运行的进程当前执行的 conda 进程使用的仍是内存中已加载的旧代码它不会因为磁盘文件被替换而切换到新代码如果新包中不再包含旧的启动器文件那么「运行中的旧代码 已被替换的磁盘文件」组合下事务将无法找到需要的启动器而失败。因此把cli-64.exe保留在新发布的包中就是为了让这些正在执行的旧版本 conda 进程能够完成其升级事务。这正是 conda/core/launchers.py 中注释「Prefer the extracted package during upgrades, before installed files are unlinked」升级期间、已安装文件被 unlink 之前优先使用解压出的包所描述的机制也是conda-launchers包在事务中尚未完成链接时代码要优先从source_package_infos正在解压的包信息而不是前缀中查找的原因。该行为自 conda 26.3.0 起引入PR #15678更早的版本在创建入口点时复制的是Scripts/conda.exe。cli-32.exewin-32 目标的回退方案cli-32.exe的角色相对单一当已安装的或本次事务选定的conda-launchers包没有提供 32 位启动器时作为回退。这与上游渠道现状直接相关releases/qa/16293-conda-launchers中说明默认渠道defaults并未为win-32提供启动器因此 conda 为win-32目标保留了自带的内置 stub。在源码层面该回退逻辑位于 conda/core/launchers.py# Retain the bundled stub until defaults publishes a 32-bit launcher. if subdir win-32: path join(CONDA_PACKAGE_ROOT, shell, cli-32.exe) if not isfile(path): raise FileNotFoundError(fMissing bundled Windows launcher {path!r}.) return ( path, 0170dda609519c088b1e4619a1e1d15a01701a6c514bb55f99a85fcbbd541631, )注意该分支附带一个硬编码的 SHA-256 摘要——即使走回退路径文件仍会经过完整性校验见下文「哈希校验」损坏的cli-32.exe无法通过。源码视角stub 的定位、校验与回退全链路要真正理解这两个文件的地位需要看它们在整个入口点创建流程中的位置。核心模块是 conda/core/launchers.py它提供两个函数get_windows_launcher_stub(target_prefix, *, source_prefixes, source_package_infos())定位目标 Python 对应的启动器路径及其期望的 SHA-256verify_windows_launcher(path, sha256)在复制前立即校验文件哈希不匹配则抛出SafetyError。平台到 stub 的映射表conda/base/constants.py 定义了WINDOWS_LAUNCHER_STUB_PATH# Paths relative to the prefix containing the conda-launchers package. WINDOWS_LAUNCHER_STUB_PATH: Final { win-32: share/conda-launchers/cli-32.exe, win-64: share/conda-launchers/cli-64.exe, win-arm64: share/conda-launchers/cli-arm64.exe, }它给出了conda-launchers包内各平台 stub 的相对路径相对安装前缀内置的shell/cli-64.exe、shell/cli-32.exe则是conda-launchers出现之前的同源文件。win-arm64也映射到cli-64.exe所在位置的 ARM64 变体cli-arm64.exe即conda-launchers提供原生 ARM64 启动器依赖 Windows 的 x64-on-ARM64 模拟兜底见 CHANGELOG.md。选择优先级事务包 前缀中已安装包 内置回退get_windows_launcher_stub的执行顺序可以概括为确定目标 subdir优先取事务中python包的 subdirsource_package_infos中名为python的repodata_record否则取目标前缀中已安装的python记录再否则回退到context.subdir。这样在交叉架构场景如 win-32 主机创建 win-64 环境也能选对 stub优先使用解压中的conda-launchers包如果本次事务包含conda-launchers直接从其解压目录中查找short_path。这就是升级场景下的「先取新文件」逻辑其次在前缀中查找遍历source_prefixes通过PrefixData(prefix).get(conda-launchers)读取已安装记录在paths_data中匹配short_path并要求该路径数据带 SHA-256缺失则抛SafetyError对应测试 tests/core/test_launchers.pywin-32 专属回退上述两步都失败且目标是win-32时回退到内置CONDA_PACKAGE_ROOT/shell/cli-32.exe否则报错找不到时抛出FileNotFoundError提示安装支持对应 subdir 的conda-launchers。上述行为均有对应单元测试覆盖见 tests/core/test_launchers.py例如test_launcher_matches_target_python按目标 subdir 精确匹配L64-L75test_launcher_matches_python_in_transaction事务中 python 为 win-arm64 时也正确选择L78-L101test_launcher_uses_extracted_package_during_upgrade升级期间优先用解压出的新 launcherL104 起test_launcher_win32_fallback*win-32 回退内置 stub 及损坏文件被哈希校验拦截L161-L217test_launcher_rejects_unsupported_targetlinux-64 等非 Windows 目标抛出NotImplementedErrorL245-L252。哈希校验与代码签名verify_windows_launcher在复制前用compute_sum(path, sha256)计算实际文件哈希并与期望值比对任何不匹配都会触发SafetyError这保证了即便选择了回退路径文件也没有被篡改或损坏对应test_launcher_win32_corrupt_fallback测试。此外tests/test_codesigned.py 中的test_stub_exe_signatures使用 Windows SDK 的signtool对WINDOWS_LAUNCHER_STUB_PATH下的所有 stub以及内置shell/cli-64.exe执行签名验证signtool verify /pa /v确保发布的启动器带有合法代码签名规避 SmartScreen 等安全提示。两个消费方conda init 与包安装事务stub 选择逻辑被两处消费1. conda init生成 Scripts/conda.execonda/core/initialize.py 的make_entry_point_exe在conda init时被调用def make_entry_point_exe(target_path, conda_prefix): from .launchers import get_windows_launcher_stub, verify_windows_launcher # target_path: join(conda_prefix, Scripts, conda.exe) exe_path target_path source_exe_path, sha256 get_windows_launcher_stub( conda_prefix, source_prefixes(conda_prefix, context.conda_prefix) ) if isfile(exe_path): if compute_sum(exe_path, sha256) sha256: return Result.NO_CHANGE ... verify_windows_launcher(source_exe_path, sha256) copy(source_exe_path, exe_path)它先比较目标文件现有哈希与期望哈希以判断是否需要更新避免无意义写入再校验源文件后复制。这也解释了 PR #16293 的变更用 SHA-256 替代 MD5 来决定conda init是否替换已有启动器见 releases/news/16293-conda-launchers-entrypoints。2. 包安装为带入口点的包生成 Scripts/.execonda/core/path_actions.py 的create_python_entry_point_windows_exe_action在处理包含entry_points元数据的 Python 包时调用get_windows_launcher_stub把选中的 stub 复制/链接为Scripts/command.exetarget_short_path fScripts/{command}.exe随后同样执行哈希校验L527-L529。安装、更新、克隆环境等操作只要涉及 Windows 入口点都会经过这条路径。这两个消费方分别覆盖「conda 自身入口点初始化」与「环境中任意 Python 包的入口点创建」也正因如此内置 stub 的生命周期牵动整个 Windows 用户群。为什么不能直接删除升级路径约束分析conda/shell/README.md 的「Removal」一节给出了明确的移除条件两个文件都没有排定的移除日期在移除之前必须为「仍然会读取它们」的已发布客户端提供安全升级路径特别指出用户可能跳过若干版本再升级所以「再保留一个发布周期」并不能解决问题——只要还有老版本客户端在运行新包就必须继续携带这些文件否则老客户端发起自升级时会失败移除cli-32.exe还额外要求受支持的conda-launchers包必须能为win-32提供 32 位启动器目前 defaults 渠道尚未提供。因此这两个文件本质上承担的是向前兼容契约它们是连接「旧 conda 进程」与「新 conda 包」之间升级事务的桥梁。相关质量保证说明见 releases/qa/16293-conda-launchers其中也提到自动测试覆盖了「文件缺失、哈希缺失、启动器损坏、事务源选择」等场景。演进脉络一览从本仓库可以还原出这段历史的完整时间线26.3.0 之前conda 创建 Windows 入口点时复制Scripts/conda.exe26.3.0PR #15678改用内置 stubconda/shell/cli-32.exe/cli-64.exe创建入口点使入口点创建不再依赖「conda 以 conda 包方式安装」例如python -m pytest运行测试时也能工作并通过平台映射表为win-arm64选择cli-64.exe同时让conda init也使用目标平台对应的 stub修复交叉架构安装见 CHANGELOG.md后续PR #16293Windows 入口点改用发布的conda-launchers包含原生 ARM64 启动器复制前校验 SHA-256conda init的替换判断改用 SHA-256 替代 MD5同时保留内置 stub用于「已发布 conda 发起的升级」以及「无 32 位启动器的包」两类场景见 releases/news/16293-conda-launchers-entrypoints。目前含 26.7.2仍处于第三阶段conda-launchers是主路径shell/cli-32.exe与shell/cli-64.exe是兼容性保留路径。开发者如果需要在 Windows 上排查「入口点 .exe 创建失败」「conda init 报启动器相关错误」等问题可以从 conda/core/launchers.py 的返回路径与 tests/core/test_launchers.py 的用例入手快速定位是「conda-launchers 缺失」「哈希不匹配」还是「回退文件损坏」所致。小结conda/shell下的cli-32.exe与cli-64.exe不是冗余资产而是 conda 在 Windows 入口点机制迁移期精心设计的兼容层cli-64.exe守护自升级事务的完成cli-32.exe填补 defaults 渠道 32 位启动器的空缺而它们的移除条件安全升级路径 上游提供 32 位启动器也清楚划定了 conda-launchers 生态成熟度的边界。理解这条链路对 conda 的二次开发、打包以及 Windows 端故障排查都有直接价值。【免费下载链接】condaA system-level, binary package and environment manager running on all major operating systems and platforms.项目地址: https://gitcode.com/GitHub_Trending/co/conda创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。