pip lock & pylock.toml

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the Python Reference bibliography.

pip lock writes the result of a resolution to a standard PEP 751 lock file, and pip install -r pylock.toml installs one. Both are experimental in pip 26.2.2: each prints a warning to that effect, and the documentation says they "may be removed/changed in a future release without prior warning". This page was written against pip 26.2.2 and run on CPython 3.14.6 on 2026-10-22 for the pip flavour of birdtally-report. The file format and how it compares with the other lock formats are on Lock Files & Reproducible Installs.

pip lock

python -m pip lock [options] <requirement specifier> ...
python -m pip lock [options] -r <requirements file> ...
python -m pip lock [options] [-e] <vcs project url> ...
python -m pip lock [options] [-e] <local project path> ...

It takes the same requirement forms as pip install and most of its resolution options (-r, -c, --build-constraint, --requirements-from-script, --only-deps, -e, --group, the index, binary and pre-release options, --uploaded-prior-to). -o/--output <path> names the output, pylock.toml by default, or - for standard output. pip resolves exactly as for an install and writes what it would install instead of installing it. The documentation’s key limitation: "The generated lock file is only guaranteed to be valid for the current python version and platform."

Locking birdtally-report

report-req.txt:

--index-url http://localhost:8080/simple
birdtally[pretty]==0.1.0
python -m pip lock -r report-req.txt
WARNING: pip lock is currently an experimental command. It may be removed/changed in a future release without prior warning.
Collecting birdtally==0.1.0 (from birdtally[pretty]==0.1.0->-r report-req.txt (line 2))
  Downloading birdtally-0.1.0-py3-none-any.whl (3.7 kB)
Collecting rich>=13 (from birdtally[pretty]==0.1.0->-r report-req.txt (line 2))
Collecting markdown-it-py>=2.2.0 (from rich>=13->birdtally[pretty]==0.1.0->-r report-req.txt (line 2))
Collecting pygments<3.0.0,>=2.13.0 (from rich>=13->birdtally[pretty]==0.1.0->-r report-req.txt (line 2))
Collecting mdurl~=0.1 (from markdown-it-py>=2.2.0->rich>=13->birdtally[pretty]==0.1.0->-r report-req.txt (line 2))

The resulting pylock.toml, with the hash values shortened and the three packages in the middle left out (they have the same shape):

lock-version = "1.0"
created-by = "pip"

[[packages]]
name = "birdtally"
version = "0.1.0"

[[packages.wheels]]
name = "birdtally-0.1.0-py3-none-any.whl"
url = "http://localhost:8080/packages/birdtally-0.1.0-py3-none-any.whl"

[packages.wheels.hashes]
sha256 = "35a50693…9984a56b5a"

[[packages]]
name = "markdown-it-py"
version = "4.2.0"

[[packages.wheels]]
name = "markdown_it_py-4.2.0-py3-none-any.whl"
url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl"

[packages.wheels.hashes]
sha256 = "9f7ebbcd…2641c4a"

…

[[packages]]
name = "rich"
version = "15.0.0"

[[packages.wheels]]
name = "rich-15.0.0-py3-none-any.whl"
url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl"

[packages.wheels.hashes]
sha256 = "33bd4ef7…e27de0bb"

Line by line:

  • lock-version = "1.0" is the version of the PEP 751 format; installers must refuse a version they do not support.

  • created-by = "pip" names the tool that wrote it.

  • There is no environments and no requires-python key: pip records nothing about the platform the lock is valid for, although it is valid only for this one. Record the Python version and platform yourself, for example in the file name (pylock.linux-py314.toml matches the pylock.<name>.toml rule, which allows no further dots).

  • Each [[packages]] entry has a name and version and exactly one source: here [[packages.wheels]] with the file name, the url and its hashes. Only the file pip chose is listed, not the other wheels or the sdist, so the lock cannot fall back to another file.

  • The private birdtally wheel is recorded by its full URL on the local index; the installer will fetch from that URL, whatever your index configuration says at install time.

  • pip 26.2.2 did not write the optional index, size or upload-time keys for these packages, which the Poetry export does write (compare the export on the lock-files page).

Installing from pylock.toml

Since pip 26.1, -r accepts a pylock.toml (or pylock.<name>.toml) as well as a requirements file. In a fresh venv:

python -m pip install -r pylock.toml
WARNING: Using pylock.toml as a requirements source is an experimental feature. It may be removed/changed in a future release without prior warning.
Collecting birdtally==0.1.0 (from pylock.toml)
  Downloading birdtally-0.1.0-py3-none-any.whl (3.7 kB)
Collecting markdown-it-py==4.2.0 (from pylock.toml)
Collecting mdurl==0.1.2 (from pylock.toml)
Collecting pygments==2.21.0 (from pylock.toml)
Collecting rich==15.0.0 (from pylock.toml)
Installing collected packages: pygments, mdurl, birdtally, markdown-it-py, rich

Successfully installed birdtally-0.1.0 markdown-it-py-4.2.0 mdurl-0.1.2 pygments-2.21.0 rich-15.0.0

As the specification requires, pip installs what the lock lists instead of resolving: a requirement that contradicts it is an error (the message was improved in 26.2):

python -m pip install --dry-run -r pylock.toml rich==14.3.4
WARNING: Using pylock.toml as a requirements source is an experimental feature. It may be removed/changed in a future release without prior warning.
ERROR: The requirement rich==14.3.4 is not compatible with version 15.0.0 specified in a provided lock file
ERROR: No matching distribution found for rich==14.3.4

pip 26.2 also made --only-final apply to packages from a lock, made --uploaded-prior-to use the lock’s upload-time field, and rejects path entries in a lock fetched from a URL when they point outside the lock file’s own location (so a remote lock cannot point at your file system or another host).

Limits, and the alternatives

pip lock 26.2.2 poetry.lock (Poetry 2.5.1) uv.lock (uv 0.13, third party)

Status

Experimental

Stable

Stable

Format

PEP 751

Poetry’s own

uv’s own (can export PEP 751)

Platforms

The current one only

All, with markers

All, with markers

Files per package

The chosen one

All files of the version

All files of the version

Groups and extras

Resolved at lock time

All, selected at install

All, selected at install

Installed by

pip 26.1+ (experimental), uv, PDM

Poetry; pip after poetry export -f pylock.toml

uv; pip after export

pip lock is a good fit for one deployment target (a container image on one Python) and as a way to produce a standard file without a workflow tool. When a project must install on several platforms from one lock, use Poetry (and export to pylock.toml for pip consumers) or another cross-platform locker.