十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

conda package 命令详解:从环境未跟踪文件创建低层 conda 包

conda package 命令详解:从环境未跟踪文件创建低层 conda 包 conda package 命令详解从环境未跟踪文件创建低层 conda 包【免费下载链接】condaA system-level, binary package and environment manager running on all major operating systems and platforms.项目地址: https://gitcode.com/GitHub_Trending/co/condaconda package是 conda 内置的一个实验性EXPERIMENTAL命令用于以“低层工具”的方式把某个环境前缀prefix中未被 conda 管理的文件打包成一个标准的.tar.bz2conda 包。这篇指南基于 官方文档页 所定义的命令接口结合 命令实现源码 与 untracked 文件计算逻辑完整讲解该命令的参数含义、三种核心用法定位文件来源、查看/清除未跟踪文件、打包成包以及打包过程底层的目录结构、shebang 重写与校验和生成机制。命令定位与文档生成方式conda package的官方帮助页docs/source/commands/package.rst是一个 Sphinx argparse 自动文档页它直接引用conda.cli.conda_argparse模块中generate_parser生成的解析器取path: package对应子命令的参数定义自动渲染出帮助内容。这意味着该命令的全部可用参数以源码为准文档页不会滞后于实现。在 conda/cli/main_package.py 中命令的注册摘要为summary Create low-level conda packages. (EXPERIMENTAL)因此conda package --help会显示这是一个“创建低层 conda 包”的实验性工具。它的典型场景是你在某个环境中手工放置了一些文件脚本、数据文件等想不经过完整的 conda-build 流程快速把“conda 不知道的文件”打成一个可分发的 tar.bz2 包。参数一览参数定义位于 configure_parser。由于调用了 add_parser_prefixconda package与其他 conda 命令一样支持目标环境指定参数参数说明备注-n,--name ENVIRONMENT指定目标环境的名称与-p互斥不指定时默认使用当前激活环境/前缀-p,--prefix PATH指定环境前缀的完整路径与-n互斥-w,--which PATH给定某个文件路径打印该文件来自哪个 conda 包可传多个路径nargs-r,--reset删除环境中所有未跟踪untracked文件后退出store_true-u,--untracked列出所有未跟踪文件后退出store_true--pkg-name指定要创建包的包名默认unknown--pkg-version指定要创建包的版本号默认0.0--pkg-build指定要创建包的 build number默认0execute入口conda/cli/main_package.py按优先级处理这些参数prefix context.target_prefix # 由 -n/-p 或当前环境决定 if args.which: # 1. 定位模式 for path in args.which: for prec in which_package(path): print(%-50s %s % (path, prec.dist_str())) return 0 if args.reset: # 2. 清除未跟踪文件 remove(prefix, untracked(prefix)) return 0 if args.untracked: # 3. 列出未跟踪文件 files sorted(untracked(prefix)) ... return 0 # 4. 默认行为把未跟踪文件打包 make_tarbz2(prefix, nameargs.pkg_name.lower(), versionargs.pkg_version, build_numberint(args.pkg_build))注意-w/-r/-u会提前返回只有不带这三个选项时命令才执行打包且--pkg-name会被强制转为小写args.pkg_name.lower()。用法一用 -w/--which 定位文件的来源包conda package -w $ENV_PREFIX/bin/ipython实现见 which_package先把输入转成绝对路径再调用 which_prefix 从该路径逐级向上dirname查找直到某个目录包含conda-meta子目录——那就是文件所在的环境前缀。如果一路走到根目录都没找到抛出CondaVerificationError提示could not determine conda prefix from: path。通过PrefixData(prefix).iter_records()遍历环境中已安装的包记录对每个记录判断其files列表是否包含该路径用paths_equal做规范化比较命中则产出该包。输出格式为“路径左对齐 50 列 包的 dist_strname-version-build”$ conda package -w $(which ipython) /opt/conda/bin/ipython ipython-8.10.0-py390由于同一文件可能被多个包声明例如元包与依赖包重叠which_package是生成器“通常迭代结果只有一个包但可能多于一个”源码注释原文如此。用法二用 -u/--untracked 查看、-r/--reset 清除未跟踪文件什么是 untracked 文件conda/misc.py 中的 untracked() 给出了精确定义def untracked(prefix, exclude_self_buildFalse): Return (the set) of all untracked files for a given prefix. conda_files conda_installed_files(prefix, exclude_self_build) return { path for path in walk_prefix(prefix) - conda_files if not ( path.endswith(~) or on_mac and path.endswith(.DS_Store) or path.endswith(.pyc) and path[:-1] in conda_files ) }即遍历前缀下所有文件walk_prefix减去 conda 实际安装的所有文件conda_installed_files来源于各包info/files的并集再剔除三类“噪音”以~结尾的编辑器临时文件macOS 上的.DS_Store与某个被 conda 管理的.py文件同名的.pyc即 conda 包自带的源码被解释器生成的字节码。因此untracked回答的是“哪些文件是安装完成后、由用户或第三方工具如 pip、setup.py新放进环境的”。conda clone内部也复用同一函数把这些文件复制到新环境中见 clone_env说明该概念是 conda 环境管理的一块基础能力。查看未跟踪文件conda package --untracked -n myenv # 输出示例 # prefix: /home/user/.conda/envs/myenv # untracked files: 3 lib/python3.9/site-packages/foo/__init__.py lib/python3.9/site-packages/foo-1.0.dist-info/RECORD scripts/foo执行流程execute先打印# prefix: 前缀再打印# untracked files: N然后逐行输出排序后的相对路径相对前缀的路径不含前缀本身。清除未跟踪文件conda package --reset -n myenv调用 remove()先对每个文件os.unlink收集其所在目录最后按路径长度从长到短尝试os.rmdir清理空目录目录非空时静默忽略except OSError: pass。⚠️ 注意-r只删除 untracked 文件即 conda 未管理的部分。conda 已安装的文件不受影响但也意味着手工安装的 pip 包、本地脚本等会被一并删除操作前建议先用-u确认清单。用法三默认行为把未跟踪文件打包成 .tar.bz2不带-w/-r/-u时命令进入打包流程 make_tarbz2conda package --pkg-namemytool --pkg-version1.2 --pkg-build3 -n myenv # 输出示例 # prefix: /home/user/.conda/envs/myenv # files: 17 # success mytool-1.2-3.tar.bz2包文件命名与元数据输出文件名格式为{name}-{version}-{build}.tar.bz2其中扩展名常量定义在 conda/base/constants.pyCONDA_PACKAGE_EXTENSION_V1: Final .tar.bz2包内info/index.json的元数据由 create_info 生成d dict( namename, versionversion, platformcontext.platform, # 如 linux-64 archcontext.arch_name, # 如 x86_64 build_numberint(build_number), buildstr(build_number), depends[], ) if requires_py: d[build] (py%d%d_ % requires_py) d[build] d[depends].append(python %d.%d* % requires_py)Python 依赖的自动推断打包时有一个关键判断make_tarbz2只要文件列表里有任何一个路径包含/site-packages/就认为该包是 Python 包此时必须在前缀中找到已安装的python通过 get_installed_version 读取PrefixData记录否则抛出ValueError(Python must be installed in target prefix.)取 Python 版本号的前三段把 build 字符串改写为pyMAJMIN_原build如py39_3并在depends中追加python MAJ.MIN*例如python 3.9*。非 site-packages 文件如纯脚本、二进制工具则不引入 Python 依赖。包内部结构实际写包由 create_conda_pkg 完成产物是一个标准的 v1 格式 tar.bz2目录结构如下mytool-1.2-3.tar.bz2 ├── info/ │ ├── files # 逐行列出包内文件相对前缀路径 │ ├── index.json # 包元数据name/version/build/depends/platform/arch/file_hash… │ └── has_prefix # 被重写过 shebang 的文件清单若存在 ├── bin/foo # 用户文件相对前缀路径 └── lib/...info/目录的写入逻辑在 _add_info_dir先写files与index.json键排序后的 JSON若存在has_prefix清单则一并写入然后把整个info目录以info/前缀追加进 tar。打包过程中的校验与警告create_conda_pkg路径合法性每个文件路径不能为空、不能以/开头或结尾、不能包含反斜杠\否则直接raise ValueError。这是为了确保包内路径始终是与前缀相对的 POSIX 风格路径。符号链接链接目标参与file_hash计算若链接指向绝对路径以/开头返回警告found symlink to absolute path: f - link。egg-link发现.egg-link文件setup.py develop 模式的残留会返回警告found egg link: f提示该文件打进包里通常没有意义。file_hash对每个文件计算sha1(相对路径 \x00 内容或符号链接目标)的累积哈希最终写入info/index.json的file_hash字段作为包内容指纹。shebang 重写机制打包时还有一个重要的移植性处理 fix_shebang对于位于bin/目录下、以#!开头且 shebang 行包含python的文件会将其第一行 shebang 替换为data shebang_pat.sub(f#!{PREFIX_PLACEHOLDER}/bin/python, data, count1) ... os.chmod(tmp_path, int(755, 8))其中 PREFIX_PLACEHOLDER 是 conda 的“前缀占位符”常量PREFIX_PLACEHOLDER: Final ( /opt/anaconda1anaconda2 # this is intentionally split into parts, such that running # this program on itself will leave it unchanged anaconda3 )拼接结果为/opt/anaconda1anaconda2anaconda3。注释解释了它的巧妙之处常量被故意拆成三段拼接使得 conda 代码自身包含这些字符串字面量的 .py 文件在“对自己执行 shebang 替换”时匹配不到完整占位符从而保持不变。安装时conda 的 portable 机制见 conda/core/portability.py 中对同一占位符的使用会把包内所有PREFIX_PLACEHOLDER替换为真实目标前缀这就是 conda 包“位置无关prefix-agnostic”的核心手法。被改写的文件会记入info/has_prefix安装端据此知道哪些文件需要按行重写前缀。一个完整的端到端示例# 1. 准备一个环境放入想要打包的文件 conda create -n pkr scripts -y conda activate pkr mkdir -p scripts cat scripts/hello.py EOF #!/usr/bin/env python print(hello from pkr) EOF # 2. 查看哪些文件尚未被 conda 跟踪 conda package --untracked # 3. 打包site-packages 判定不触发因为文件在 scripts/ 下 conda package --pkg-namepkr-tools --pkg-version0.1 --pkg-build0 # # success # pkr-tools-0.1-0.tar.bz2 # 4. 用完后还原环境 conda package --reset适用前提与注意事项实验性命令源码中标注(EXPERIMENTAL)其产物是 v1 格式.tar.bz2而非新版.conda格式从源码结构看若需要面向现代通道的发布流程仍建议以 conda-build 等完整工具链为准conda package更适合快速验证与轻量场景。打包内容 untracked 文件--pkg-name/--pkg-version/--pkg-build只决定元数据文件清单始终来自untracked()无法通过参数指定“只打某些文件”。若环境里混有大量不想包含的未跟踪文件需先清理或在干净环境中操作。-r/--reset不可恢复删除的是 conda 未管理文件执行前务必用-u先预览。平台绑定info/index.json中的platform/arch取自打包机context.platform、context.arch_name且 build 字符串在含 site-packages 时会自动加pyMAJMIN_前缀因此该包本质上是与打包平台/Python 主版本绑定的。文档页与源码同步docs/source/commands/package.rst 由 argparse 自动生成如需确认最新参数包括--name/--prefix这类通用前缀参数以conda package --help或 conda/cli/main_package.py 的configure_parser为准。小结conda package把 conda 环境管理中的一个底层概念——“前缀中未被 conda 跟踪的文件”——暴露成了三个实用动作-w反查文件归属包、-u/-r查看与清除未跟踪文件、默认动作则将未跟踪文件连同自动生成的info/files、info/index.json含file_hash、Python 依赖推断和PREFIX_PLACEHOLDERshebang 重写打成一个标准的 v1 tar.bz2 包。理解它的关键在于理解 untracked() 的集合差定义与 create_conda_pkg() 的包构建流程——这两处源码也是 conda 克隆环境、portability 机制共用的基础。【免费下载链接】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),仅供参考
返回列表