高级用法
自动化测试
使用 Tox 作为运行器
Tox 是一个很棒的工具,用于在多个 Python 版本或依赖集上进行测试。您可以配置一个 tox.ini
,如下所示,以将您的测试与 PDM 集成:
[tox]
env_list = py{36,37,38},lint
[testenv]
setenv =
PDM_IGNORE_SAVED_PYTHON="1"
deps = pdm
commands =
pdm install --dev
pytest tests
[testenv:lint]
deps = pdm
commands =
pdm install -G lint
flake8 src/
要使用 Tox 创建的虚拟环境,您应该确保已设置 pdm config python.use_venv true
。然后 PDM 将从 pdm lock
将依赖项安装到虚拟环境中。在专用的 venv 中,您可以直接运行工具,例如 pytest tests/
,而不是 pdm run pytest tests/
。
您还应确保在测试命令中不要运行 pdm add/pdm remove/pdm update/pdm lock
,否则 pdm lock
文件将被意外修改。可以使用 deps
配置提供额外的依赖项。此外,isolated_build
和 passenv
配置应按上述示例设置,以使 PDM 正常工作。
为了摆脱这些限制,有一个 Tox 插件 tox-pdm 可以简化使用。您可以通过以下方式安装它:
pip install tox-pdm
或者,
pdm add --dev tox-pdm
然后,您可以使 tox.ini
更加整洁,如下所示:
[tox]
env_list = py{36,37,38},lint
[testenv]
groups = dev
commands =
pytest tests
[testenv:lint]
groups = lint
commands =
flake8 src/
查看 项目的 README 以获取详细指南。
使用 Nox 作为运行器
Nox 是另一个用于自动化测试的优秀工具。与 tox 不同,Nox 使用标准的 Python 文件进行配置。
在 Nox 中使用 PDM 更容易,以下是 noxfile.py
的示例:
```python hl_lines=”4” import os import nox
os.environ.update({“PDM_IGNORE_SAVED_PYTHON”: “1”})
@nox.session def tests(session): session.run_always(‘pdm’, ‘install’, ‘-G’, ‘test’, external=True) session.run(‘pytest’)
@nox.session def lint(session): session.run_always(‘pdm’, ‘install’, ‘-G’, ‘lint’, external=True) session.run(‘flake8’, ‘—import-order-style’, ‘google’)
请注意,应设置 `PDM_IGNORE_SAVED_PYTHON`,以便 PDM 可以正确地在虚拟环境中获取 Python。还要确保 `pdm` 在 `PATH` 中可用。在运行 nox 之前,您还应确保配置项 `python.use_venv` 为 true,以启用 venv 重用。
### 关于 PEP 582 `__pypackages__` 目录
默认情况下,如果您通过 [`pdm run`](../reference/cli.md#run) 运行工具,`__pypackages__` 将被程序及其创建的所有子进程看到。这意味着由这些工具创建的虚拟环境也了解 `__pypackages__` 内的包,这在某些情况下会导致意外行为。
对于 `nox`,您可以通过在 `noxfile.py` 中添加一行来避免这个问题:
```python
os.environ.pop("PYTHONPATH", None)
对于 tox
,PYTHONPATH
不会传递给测试会话,所以这不会成为问题。此外,建议让 nox
和 tox
位于它们自己的 pipx 环境中,这样您就不需要为每个项目安装。在这种情况下,PEP 582 包也不会成为问题。
在持续集成中使用 PDM
只需记住一件事 —— PDM 无法在 Python < 3.7 上安装,所以如果您的项目需要在这些 Python 版本上进行测试,您必须确保 PDM 已在正确的 Python 版本上安装,这可能与特定作业/任务运行的目标 Python 版本不同。
幸运的是,如果您正在使用 GitHub Action,有 pdm-project/setup-pdm 可以让这个过程变得更容易。以下是一个 GitHub Actions 的示例工作流程,您可以将其适应于其他 CI 平台。
Testing:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: [3.7, 3.8, 3.9, '3.10', '3.11']
os: [ubuntu-latest, macOS-latest, windows-latest]
steps:
- uses: actions/checkout@v3
- name: Set up PDM
uses: pdm-project/setup-pdm@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
pdm sync -d -G testing
- name: Run Tests
run: |
pdm run -v pytest tests
!!! 重要 “提示”
对于 GitHub Action 用户,Ubuntu 虚拟环境上存在一个已知的兼容性问题。
如果在那台机器上 PDM 并行安装失败,您应该将 parallel_install
设置为 false
,或者设置环境变量 LD_PRELOAD=/lib/x86_64-linux-gnu/libgcc_s.so.1
。
pdm-project/setup-pdm
操作已经处理了这个问题。
!!! 注意 如果您的 CI 脚本在没有正确设置用户的情况下运行,当 PDM 尝试创建其缓存目录时,您可能会遇到权限错误。 要解决这个问题,您可以自己设置 HOME 环境变量,到一个可写的目录,例如:
```bash
export HOME=/tmp/home
```
在多阶段 Dockerfile 中使用 PDM
可以在多阶段 Dockerfile 中使用 PDM,首先将项目和依赖项安装到 __pypackages__
中,然后将该文件夹复制到最终阶段,并添加到 PYTHONPATH
。
ARG PYTHON_BASE=3.10-slim
# 构建阶段
FROM python:$PYTHON_BASE AS builder
# 安装 PDM
RUN pip install -U pdm
# 禁用更新检查
ENV PDM_CHECK_UPDATE=false
# 复制文件
COPY pyproject.toml pdm.lock README.md /project/
COPY src/ /project/src
# 将依赖项和项目安装到本地包目录
WORKDIR /project
RUN pdm install --check --prod --no-editable
# 运行阶段
FROM python:$PYTHON_BASE
# 从构建阶段检索包
COPY --from=builder /project/.venv/ /project/.venv
ENV PATH="/project/.venv/bin:$PATH"
# 设置命令/入口点,适应您的需求
COPY src /project/src
CMD ["python", "src/__main__.py"]
使用 PDM 管理单体仓库
使用 PDM,您可以在单个项目中拥有多个子包,每个子包都有自己的 pyproject.toml
文件。并且您可以创建只有一个 pdm.lock
文件来锁定所有依赖项。子包可以相互作为它们的依赖项。要实现这一点,请按照以下步骤操作:
project/pyproject.toml
:
[tool.pdm.dev-dependencies]
dev = [
"-e file:///${PROJECT_ROOT}/packages/foo-core",
"-e file:///${PROJECT_ROOT}/packages/foo-cli",
"-e file:///${PROJECT_ROOT}/packages/foo-app",
]
packages/foo-cli/pyproject.toml
:
[project]
dependencies = ["foo-core"]
packages/foo-app/pyproject.toml
:
[project]
dependencies = ["foo-core"]
现在,在项目根目录下运行 pdm install
,您将得到一个锁定所有依赖项的 pdm.lock
。所有子包将以可编辑模式安装。
查看 🚀 示例仓库 了解更多详情。
pre-commit
的钩子
pre-commit
是一个强大的框架,用于集中管理 git 钩子。PDM 已经使用 pre-commit
钩子 进行其内部质量检查。PDM 还公开了几个可以本地或在 CI 管道中运行的钩子。
导出 requirements.txt
此钩子包装了命令 pdm export
以及任何有效的参数。它可以用作钩子(例如,用于 CI),以确保您将要签入代码库的 requirements.txt
反映了 pdm lock
的实际内容。
# 导出 Python 需求
- repo: https://github.com/pdm-project/pdm
rev: 2.x.y # 公开钩子的 PDM 版本
hooks:
- id: pdm-export
# 命令参数,例如:
args: ['-o', 'requirements.txt', '--without-hashes']
files: ^pdm.lock$
检查 pdm.lock
是否与 pyproject.toml 保持最新
此钩子包装了命令 pdm lock --check
以及任何有效的参数。它可以用作钩子(例如,用于 CI),以确保每当 pyproject.toml
有依赖项被添加/更改/删除时,pdm.lock
也是最新的。
- repo: https://github.com/pdm-project/pdm
rev: 2.x.y # 公开钩子的 PDM 版本
hooks:
- id: pdm-lock-check
将当前工作集与 pdm.lock
同步
此钩子包装了命令 pdm sync
以及任何有效的参数。它可以用作钩子,以确保每当您检出或合并一个分支时,您的当前工作集与 pdm.lock
同步。如果您想要使用系统的凭证存储,请在 additional_dependencies
中添加 keyring。
- repo: https://github.com/pdm-project/pdm
rev: 2.x.y # 公开钩子的 PDM 版本
hooks:
- id: pdm-sync
additional_dependencies:
- keyring