ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

PDM 锁定目标(Lock Targets):为特定平台与 Python 版本生成独立锁文件

PDM 锁定目标(Lock Targets):为特定平台与 Python 版本生成独立锁文件 PDM 锁定目标Lock Targets为特定平台与 Python 版本生成独立锁文件【免费下载链接】pdmA modern Python package and dependency manager supporting the latest PEP standards项目地址: https://gitcode.com/GitHub_Trending/pd/pdmPDMPython Development Master默认生成的锁文件会尽力兼容pyproject.toml中requires-python声明的全部 Python 版本与所有平台这在日常开发中非常方便在开发环境生成一次锁文件即可在 CI/CD 或生产环境原样复现依赖版本。但当项目存在平台相关依赖、或按 Python 版本区分的条件依赖时单一分辨率根本无法同时满足所有环境。本文围绕docs/usage/lock-targets.md展开系统讲解 PDM 的锁定目标Lock Targets机制——包括--python、--platform、--implementation、--append等核心参数、多锁文件与单锁文件的组织策略并结合仓库源码说明其底层解析与校验逻辑帮助你在复杂依赖场景下正确生成、组织和使用多目标锁文件。为什么需要锁定目标条件依赖的解析困境PDM 在默认情况下会生成一个“跨平台、跨 Python 版本”的锁文件即把requires-python声明的所有 Python 版本纳入考虑范围尝试对每个包求出一个在所有环境下都成立的版本解。开发阶段这种做法的收益很直接锁文件只在开发机上生成一次CI 与生产环境无需各自执行解析。然而一旦项目出现平台相关依赖或随 Python 版本变化的条件依赖这种“一锁解千愁”的模式就会失效。例如[project] name myproject requires-python 3.9 dependencies [ numpy1.25; python_version 3.9, numpy1.25; python_version 3.9, pywin32; sys_platform win32, ]这里numpy的版本选择依赖python_version而pywin32只存在于 Windows。若试图在requires-python 3.9的全范围内对每个包求出唯一版本几乎不可能得到一个同时满足所有平台与 Python 版本的解析结果。此时正确的做法就是为特定的平台或 Python 版本分别生成锁文件——这正是 PDM 2.17.0 引入的锁定目标机制。生成锁文件时指定锁定目标pdm lock命令定义于 src/pdm/cli/commands/lock.py提供一组 “Lock Target” 参数用于限定锁文件的适用环境。这些环境判据包括三类--pythonPYTHON_RANGE一个符合 PEP 440 规范的 Python 版本限定符。例如--python3.9,3.10会为3.9且3.10的 Python 版本生成锁文件。为方便起见--python3.10等价于--python3.10表示面向 3.10 及以上版本解析。--platformPLATFORM平台限定符。例如pdm lock --platformlinux为 Linux x86_64 平台生成锁文件。可选值包括linuxwindowsmacosalpinewindows_amd64windows_x86windows_arm64macos_arm64macos_x86_64macos_X_Y_arm64macos_X_Y_x86_64manylinux_X_Y_x86_64manylinux_X_Y_aarch64musllinux_X_Y_x86_64musllinux_X_Y_aarch64从 src/pdm/models/markers.py 的EnvSpec.replace()实现可以看到传入的 platform 字符串会经由Platform.parse()解析成结构化的平台对象像manylinux_X_Y_x86_64、macos_13_arm64这类带版本/架构的形态可用于锁定 glibc/musl 或 macOS 的特定版本组合。--implementationcpython|pypy|pystonPython 实现限定符目前仅支持cpython、pypy、pyston三种。三个判据可以任意组合也可以只指定其中一部分。例如只指定--platformlinux时生成的锁文件适用于 Linux 平台、但覆盖所有 Python 实现Implementation不设限。在 src/pdm/cli/commands/lock.py 中可以看到只有--python、--platform、--implementation三者中至少指定一个时才会构造env_spec命令随后通过project.environment.allow_all_spec.replace(**replace_dict)得到具体的锁定目标EnvSpec。python 判据与 requires-python 的关系需要特别注意的是--python参数以及锁文件中的requires_python判据仍然受pyproject.toml中requires-python的约束两者取交集。例如requires-python为3.9而你指定--python3.11则最终的锁定目标 Python 范围是3.9,3.11。这一逻辑在 src/pdm/cli/actions.py 的do_lock中有明确实现锁定时会把project.environment.python_requires即项目声明的requires-python与每个目标的requires_python做交集运算若交集为空则抛出PdmUsageError提示“该目标要求的 Python 范围与项目的 requires-python 不兼容”否则用合并后的范围替换目标。tests/cli/test_lock.py中的test_forbidden_lock_target_options也验证了诸如--python 3.6与项目范围无交集时命令会报错退出。多锁定文件的组织分文件或合并当项目需要不止一个锁定目标时PDM 同时支持两种组织方式为每个目标生成独立的锁文件或把多个目标的解析结果合并进同一个锁文件。方式一为每个目标生成独立锁文件# 为 Linux 平台和 Python 3.9 生成锁文件结果写入 py38-linux.lock pdm lock --platformlinux --python3.9.* --lockfilepy38-linux.lock之后在 Linux Python 3.9 的环境安装依赖时直接指定该锁文件即可pdm install --lockfilepy38-linux.lock这种方式的优点在于每个锁文件职责单一、体积可控缺点是需要手动维护多个锁文件的同步更新。此外pdm lock也支持配合--group/--with/--without等组选择参数为某个锁文件只锁定部分依赖组详见 docs/usage/lockfile.md。方式二用 --append 把多目标合并进同一锁文件# 为 Linux 平台和 Python 3.9 生成锁文件并把结果追加到 pdm.lock pdm lock --platformlinux --python3.9.* --append不加--append时新的锁定目标会覆盖原锁文件加了--append后新目标的解析结果会被追加到现有锁文件中与已有目标并存。src/pdm/cli/actions.py的do_lock中有一段关键处理追加前会先检查env_spec是否已存在于locked_repo.targets若已存在则直接打印 “Lock target ... already exists, skip locking.” 并跳过重复解析tests/cli/test_lock.py中的相关用例也断言了这一行为。同时--append与--refresh、--strategy-change如-S cross_platform等操作互斥源码中会抛出PdmUsageError予以拒绝。单锁文件的优势在于更新依赖时不必逐个同步多个文件。但代价也同样明显无法为不同的目标配置不同的锁定策略lock strategy更新锁的解析耗时预期会更高因为需要为多个目标分别求解。灵活组合锁文件与锁定目标的多对多每个锁文件可以包含一个或多个锁定目标因此组织方式非常灵活可以把某些目标合并进一个锁文件把特定组与特定目标放进另外的独立锁文件按需混搭。下一节的完整示例将展示这种组合用法。完整示例三平台两版本的项目假设pyproject.toml内容如下[project] name myproject requires-python 3.9 dependencies [ numpy1.25; python_version 3.10, numpy1.25; python_version 3.10, pandas ] [project.optional-dependencies] windows [pywin32] macos [pyobjc]该项目的numpy按 Python 版本3.10 为分界选取不同版本同时存在面向 Windows 与 macOS 的平台相关可选依赖。现在希望为 Linux、Windows、macOS 三个平台以及 Python 3.9、3.10 两种版本生成锁文件。按顺序执行以下命令pdm lock --python3.10 pdm lock --python3.10 --append pdm lock --platformwindows --python3.10 --lockfilepy310-windows.lock --with windows pdm lock --platformmacos --python3.10 --lockfilepy310-macos.lock --with macos执行后共得到 3 个锁文件pdm.lock默认主锁文件适用于所有平台以及3.9范围内的 Python 版本不包含平台相关依赖。该锁文件内包含两个版本的numpy分别适用于 3.10 及以上与 3.10 以下PDM 安装器会根据实际 Python 版本自动挑选正确的那个。目标合并的过程依赖--append第二条命令把3.10的目标追加进pdm.lock与第一条命令的3.10目标并存。py310-windows.lock面向 Windows 平台与 Python 3.10 及以上通过--with windows包含 Windows 平台的可选依赖pywin32。py310-macos.lock面向 macOS 平台与 Python 3.10 及以上通过--with macos包含 macOS 平台的可选依赖pyobjc。目标匹配与安装时的选择逻辑上述示例中pdm.lock内含两个目标安装时 PDM 如何选择在 src/pdm/cli/actions.py 的安装解析流程中PDM 会先根据当前环境构造env_spec检查其是否精确命中locked_repo.targets若未命中则比较当前环境与各目标的兼容性EnvCompatibility优先选取不高于当前环境的宽松目标找不到任何兼容目标时才会报错提示。这意味着锁文件中的多目标与当前环境按“最贴近”原则匹配从而保证在 CI 的不同平台上各取所需。锁定目标在锁文件中的表现合并了多个目标的锁文件会在元数据中记录目标列表。查看 src/pdm/project/lockfile/pdmlock.py 可以看到生成锁文件时metadata中会写入targets: [t.as_dict() for t in repository.targets]与groups、strategy、lock_version等字段并列每个目标在锁文件中以包含requires_python、platform、implementation等字段的形式持久化。正因为目标信息被完整记录后续pdm install、pdm sync、pdm update才能依据目标列表做精确匹配与增量追加。另外值得留意的是旧的cross_platform锁定策略已在新版 PDM 中被标记为弃用官方提示其被新的 lock targets 机制取代src/pdm/cli/actions.py 中会打印弃用警告并指向本文所讲的功能文档。在 tests/cli/test_lock.py 中test_lock_specific_platform_wheels还验证了指定平台锁定后锁文件中的 wheel 文件哈希列表会随平台收窄——例如同一包在 Windows 目标下可能收录 2 个 wheel而在 Linux 目标下只收录 1 个同时锁策略中不再包含cross_platform标志说明解析确实按单平台收敛。小结锁定目标机制让 PDM 从“一锁全平台”的默认模式进化出按平台、Python 版本与 Python 实现精细切分的解析能力。关键要点可概括为默认跨环境不加任何目标参数时PDM 在requires-python范围内尽量求一个通用解三类判据--pythonPEP 440 范围、--platform含 manylinux/musllinux/macOS 细分形态、--implementationcpython/pypy/pyston可组合、可省略交集约束--python最终范围会与requires-python取交集冲突时报错两种组织方式独立锁文件配合--lockfile或单文件多目标配合--append前者便于隔离管理后者便于统一更新安装自动匹配多目标锁文件在安装时会按当前环境选择最贴近的目标无需人工干预。在 CI 矩阵、多平台分发等复杂依赖场景中善用锁定目标即可在“单文件简单性”与“多环境精确性”之间找到最适合项目的平衡点。该功能从 PDM 2.17.0 起提供完整命令参数与行为也可通过pdm lock --help查看。【免费下载链接】pdmA modern Python package and dependency manager supporting the latest PEP standards项目地址: https://gitcode.com/GitHub_Trending/pd/pdm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表