pip recently gained a lock command. Run it for requests and it writes a file
named pylock.toml.
$ pip lock requests -o pylock.toml
Right now poetry, pipenv, uv and the rest each produce their own lock file, and since the specs differ there’s no compatibility between tools (because there’s no standard spec).
Last year PEP 751 was accepted and gave lock files a standard.1 In April, pip added experimental pylock.toml support. I’d guess other tools will gradually pick up the standard too. uv, for what it’s worth, already supports it.
Lock files differ by tool
A lock file records not just package versions but the hashes of the files that actually get installed, so the same conditions give you a consistent install.
In pip, requirements.txt has been playing that role almost as a de facto
standard (pip install -r requirements.txt..), but it isn’t a format that pins
versions or install files as strictly as a lock file, so depending on how you use
it, the install result can vary.
The other package tools each made their own lock file spec, and since the formats differ, building a tool like Dependabot that has to parse dependencies for inspection means supporting several lock formats. That’s a chore. PEP 751 looks like it was accepted to cut the maintenance cost of lock formats that differ from tool to tool.
The pylock.toml structure
The pylock.toml created above lists requests and the packages requests
depends on. Here is an excerpt.
lock-version = "1.0"
created-by = "pip"
[[packages]]
name = "certifi"
version = "2026.6.17"
[[packages.wheels]]
name = "certifi-2026.6.17-py3-none-any.whl"
url = "https://files.pythonhosted.org/packages/.../certifi-2026.6.17-py3-none-any.whl"
[packages.wheels.hashes]
sha256 = "2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db"
[[packages]]
name = "requests"
version = "2.34.2"
[[packages.wheels]]
name = "requests-2.34.2-py3-none-any.whl"
url = "https://files.pythonhosted.org/packages/.../requests-2.34.2-py3-none-any.whl"
[packages.wheels.hashes]
sha256 = "2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0"
A requirements file with pinned versions is usually package==version, but
looking at the structure above, it also includes the actual files to install and
their hashes on top of the version (if you want the full
pylock.toml spec, see the
docs).
pip’s current implementation
PEP 751 is accepted, but pip’s support for pip lock and -r pylock.toml is
still experimental. How pip turns the spec into features may still change (so
for now, avoid using it in production).
The limits of what’s implemented so far are being discussed in the
pip lock issue and the
-r pylock.toml issue, so if you
try it and notice something to improve, it’d be worth filing an issue.
References
- PEP 751: A file format to record Python dependencies for installation reproducibility
- pylock.toml Specification (PyPA specs)
- pip documentation,
pip lock - What’s next for
pip lock? (pypa/pip#13953) - What’s next for
-r pylock.toml? (pypa/pip#13952)