Skip to content

How to create a pylock.toml lockfile

A PEP 751 pylock.toml is the first standards-track lockfile installers with PEP 751 support can read, but the spec only defines the file, not how to produce one. Tools that produce pylock.toml include uv, pip (experimental), and PDM. This page shows the exact command for each, then recommends which producer fits which workflow.

The companion page How to install from a pylock.toml lockfile with pip covers the consumption side.

Decide which producer fits your stack

Producer Command Cross-platform Status
uv uv export --format pylock.toml -o pylock.toml Yes Stable
pip pip lock -e . -o pylock.toml No (current platform/Python only) Experimental
PDM pdm export -f pylock -o pylock.toml Yes Experimental

The short version: prefer uv export when uv manages the project’s dependencies; fall back to pip lock only when pip is the single tool allowed in the environment; use pdm export if PDM is already the project’s package manager.

Export a pylock.toml from a uv project

uv export checks and updates the project’s lockfile before exporting it to a different format; use --locked to require that the lockfile remain unchanged. PEP 751 is one of three supported outputs (requirements.txt and cyclonedx1.5 are the other two).

uv export --format pylock.toml -o pylock.toml

For a project declaring requires-python = ">=3.13" with anyio==4.13.0 locked as an httpx dependency, an export excerpt looks like this. Artifact URLs are abbreviated with ...; use the generated file for installation.

pylock.toml
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.13"

[[packages]]
name = "anyio"
version = "4.13.0"
index = "https://pypi.org/simple"
sdist = { url = "https://files.pythonhosted.org/packages/19/14/.../anyio-4.13.0.tar.gz", upload-time = 2026-03-24T12:59:09Z, size = 231622, hashes = { sha256 = "334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc" } }
wheels = [{ url = "https://files.pythonhosted.org/packages/da/42/.../anyio-4.13.0-py3-none-any.whl", upload-time = 2026-03-24T12:59:08Z, size = 114353, hashes = { sha256 = "08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708" } }]

Warning

Do not commit an export that contains hashes = {}. PEP 751 requires at least one hash per archive, source distribution, and wheel. uv reads or downloads artifacts when the source does not provide hashes, calculates SHA-256, and writes a valid table. If the file contains an empty artifact hash table or uv warns about one, update uv and rerun the original uv export or uv pip compile command; a future uv release will reject empty artifact hash tables.

The exported file preserves the cross-platform resolution from uv.lock, but installation still requires a supported Python version and platform, accessible artifacts, and any required build tools. Re-export after every uv lock (or every uv add, which calls uv lock internally) so the file stays in sync with the project’s primary lockfile.

Note

uv keeps uv.lock as the primary source of truth and treats pylock.toml as an export target. The handbook’s uv lockfile reproducibility guide explains why, and the PEP 751 page covers the metadata pylock.toml does not yet standardize.

Generate a pylock.toml with pip lock

pip provides an experimental pip lock command. It accepts the same inputs as pip install: a local project, a requirement specifier, or a requirements.txt.

# From a project in the current directory
pip lock -e . -o pylock.toml

# From a requirements file
pip lock -r requirements.txt -o pylock.toml

pip prints an experimental warning every run:

WARNING: pip lock is currently an experimental command. It may be removed/changed in a future release without prior warning.

The biggest practical limit shows up in pip lock --help:

The generated lockfile is only guaranteed to be valid for the current python version and platform.

A pylock.toml produced by pip lock on macOS for Python 3.13 is only safe to install on macOS with Python 3.13. Producing a cross-platform file means running pip lock once per target platform and Python version, and the result is still one file per environment, not a single universal lockfile. Multi-Python and multi-platform resolution is tracked in pip’s open lockfile discussions.

If pip is not the only tool available, the cross-platform output from uv export or pdm export is the lower-friction path.

Export a pylock.toml from a PDM project

PDM supports the pylock export format. Like uv’s export, it derives from the project’s existing pdm.lock.

pdm export -f pylock -o pylock.toml

The header carries PDM’s group and environment metadata along with the standard PEP 751 fields:

pylock.toml
lock-version = "1.0"
requires-python = ">=3.13"
environments = [
    "python_version >= \"3.13\"",
]
extras = []
dependency-groups = ["default"]
default-groups = ["default"]
created-by = "pdm"

PDM has signalled that pylock.toml will eventually replace pdm.lock as the project’s default format. Use pdm config lock.format pylock to lock to pylock.toml directly; use pdm export to export an existing pdm.lock.

Verify the file installs cleanly

A pylock.toml is only useful if a real installer can consume it. After producing one, run a round-trip check in a fresh virtual environment:

# With pip 26.1 or newer
pip install -r pylock.toml --no-deps

# With uv
uv pip install -r pylock.toml

--no-deps is important for pip: without it, pip resolves transitive dependencies on top of the lockfile, which defeats the point of locking. See How to install from a pylock.toml lockfile with pip for the full set of install-side caveats.

Watch nab, the successor to the pip-tools pip-lock proposal

The original pip-tools pull request for a pip-lock command (jazzband/pip-tools#2380) was closed in May 2026 after maintainers asked for it to be split into smaller reviews. The author pivoted the work to a standalone project: nab, an experimental PubGrub-based resolver written in Python that reads pyproject.toml and writes PEP 751 lockfiles. nab’s lockfile design targets: a single pylock.toml covering multiple Python versions, multiple platforms, and (optionally) multiple variants for projects with declared group conflicts. nab is pre-1.0 and its APIs are marked unstable, so this is still a “watch this space” rather than a current option.

Last updated on