# How to create a pylock.toml lockfile

A [PEP 751](https://pydevtools.com/handbook/explanation/what-is-pep-751.md) `pylock.toml` is the first standards-track [lockfile](https://pydevtools.com/handbook/explanation/what-is-a-lock-file.md) every Python installer can read, but the spec only defines the *file*, not how to produce one. As of May 2026, three tools ship working `pylock.toml` producers: [uv](https://pydevtools.com/handbook/reference/uv.md), [pip](https://pydevtools.com/handbook/reference/pip.md) (experimental since 25.1), and [PDM](https://pydevtools.com/handbook/reference/pdm.md). 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](https://pydevtools.com/handbook/how-to/how-to-install-from-a-pylock-toml-lockfile-with-pip.md) 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 (2.24.0+) |

The short version: prefer `uv export` if any Python tool in the project is uv-compatible; 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` converts the project's existing `uv.lock` to a different format. PEP 751 is one of three supported outputs (`requirements.txt` and `cyclonedx1.5` are the other two).

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

Running this in a uv project that depends on `httpx` writes a file that begins:

```toml {filename="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" } }]
```

The exported file inherits the cross-platform resolution that `uv.lock` already captures, so the same `pylock.toml` installs cleanly on macOS, Linux, and Windows. 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](https://pydevtools.com/handbook/reference/uv.md) explains why, and the PEP 751 page covers [the metadata pylock.toml does not yet standardize](https://pydevtools.com/handbook/explanation/what-is-pep-751.md).

## Generate a pylock.toml with pip lock

pip 25.1 (April 2025) added an experimental `pip lock` command; the behavior in 26.1 is unchanged. It accepts the same inputs as `pip install`: a local project, a requirement specifier, or a `requirements.txt`.

```bash
# 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:

```text
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 lock file 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](https://github.com/pypa/pip/issues?q=is%3Aopen+label%3A%22C%3A+lockfile%22).

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 2.24.0 (May 2025) added a `pylock` export format. Like uv's export, it derives from the project's existing `pdm.lock`.

```bash
pdm export -f pylock -o pylock.toml
```

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

```toml {filename="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. PDM 2.25.0 added an opt-in `pdm config lock.format pylock` switch to lock to `pylock.toml` directly rather than exporting; for most workflows the export command above is enough.

## 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:

```bash
# 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](https://pydevtools.com/handbook/how-to/how-to-install-from-a-pylock-toml-lockfile-with-pip.md) 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](https://github.com/jazzband/pip-tools/pull/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](https://github.com/notatallshaw/nab), an experimental PubGrub-based resolver written in Python that reads `pyproject.toml` and writes [PEP 751](https://pydevtools.com/handbook/explanation/what-is-pep-751.md) lockfiles. The design goal is the missing capability in the table above: 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.

## Learn More

- [uv: A Complete Guide](https://pydevtools.com/handbook/explanation/uv-complete-guide.md) covers what uv does, how fast it is, the core workflows, and recent releases.
- [What is PEP 751?](https://pydevtools.com/handbook/explanation/what-is-pep-751.md) covers the format the producers above all write to.
- [Why pylock.toml includes digital attestations](https://pydevtools.com/handbook/explanation/why-pylock-toml-includes-digital-attestations.md) explains the publisher-identity fields each producer writes.
- [pip lock command reference](https://pip.pypa.io/en/stable/cli/pip_lock/) is the official pip documentation.
- [uv export documentation](https://docs.astral.sh/uv/concepts/projects/export/) covers the full set of `uv export` flags.
- [PDM lockfile documentation](https://pdm-project.org/en/latest/usage/lockfile/) walks the PDM-side configuration.
