Python Enhancement Proposal (PEP) 751 gives Python a new file format for specifying dependencies. This file, called a lock file, promises to allow developers to reproduce the installation of their Python projects, with the exact same sets of dependencies, from system to system.
Although there are several community solutions, Python has historically lacked an official way to do file locking and conflict resolution for dependencies. The closest thing to a native solution is the requirements.txt
file, or the output from pip freeze
. The requirements.txt
file lists requirements for a project, and possible ranges of versions for each requirement. But it doesn’t address where those requirements should come from, how to validate them against a hash, or many other needs lock files commonly address today.
Individual project management tools like Poetry or uv
do their best to resolve conflicts between dependencies and record them in lock files. The bad news: Those lock files have no common format, so they’re not interchangeable between tools. They’re typically created in place by each user when installing a project’s requirements, rather than created by the developer and redistributed.
What is a lock file and why it matters
Lock files allow the dependencies of a project to be reproduced reliably, no matter where the project may be set up. Ideally, the lock file lists each dependency, where to find it, a hash to verify it, and any other information someone might need to recreate the dependency set.
Python projects typically don’t have the massive, sprawling dependency sets that can appear in, say, JavaScript projects. But even projects with only a few dependencies can have conflicts.
Imagine you have a dependency named fixthis
, which in turn depends on a package named fixerupper
. However, fixthis
depends specifically on version 1.5 of fixerupper
, because later versions have behaviors that fixthis
hasn’t addressed yet.
That by itself isn’t a problem, because you can just install fixthis
and have version 1.5 of fixerupper
installed automatically. The problem comes when other dependencies in your project might also use fixerupper
.
Let’s say we add another dependency to our project, fixthat
, which also depends on fixerupper
. However, fixthat
only works with version 2.0 or higher of fixerupper
. That means fixthis
and fixthat
can’t coexist.
On the other hand, let’s say we had an alternative package, fixit
, that could work with version 1.5 of fixerupper
or higher. Then both fixthis
and fixit
could work with version 1.5 of fixerupper
. Our project’s lock file could record the way this conflict was resolved, allowing other users to install the exact same dependencies and versions needed to avoid any deadlocks or conflicts.
What PEP 751 does for Python
PEP 751, finalized after much back-and-forth since July 2024, describes a common lock file format for Python projects to address many of the concerns described above.
The file, typically named pylock.toml
, uses the TOML data format, just like the standard Python project description file pyproject.toml
. A pylock.toml
file can be written by hand, but the idea is that you should not have to do so. Existing tools will in time generate pylock.toml
automatically, in the same way a requirements.txt
file can be generated with pip freeze
from a project’s virtual environment.
The pylock.toml
file allows for a wide range of details. It can specify which version of the lock file standard to use (if it changes in the future), which version of Python to use, what environment markers to respect for different Python versions, and package-level specifiers for much of this information as well. Each specified dependency can have details about its sourcing (including from version control systems), hashes, source distribution info (if any), and more.
A detailed example of the pylock.toml
format is available in PEP 751. Each dependency has its own [[packages]]
subsection, with details about where and when it was obtained, its hash, version requirements, and so on. The example shows how a package can have multiple platform-specific sources. In the example, numpy
lists binary wheels for Microsoft Windows and generic Linux systems.
When will PEP 751 lock files arrive?
As of this writing, there’s no official or third-party tool that supports pylock.toml
today. Future revisions of tools, from pip
on outwards, are meant to adopt pylock.toml
at the pace their providers find suitable, so you can expect the new lock file to be added to workflows and to the makeup of projects over time. You will eventually want to think about whether the set of dependencies of your project is complex enough to demand a pylock.toml
file. Anyone creating a package hosted on PyPI, for instance, will want to gravitate towards creating a pylock.toml
for the project.
The speed of adoption will be dictated by how soon existing tools make it possible to generate pylock.toml
files, and whether that file format will immediately replace their own internal formats. Some third-party tools that generate their own lock files remain hesitant to use pylock.toml
as a full replacement. uv
, for instance, intends to support pylock.toml
as an export and import format, but not as the format for its native lock files due to some features not yet supported in pylock.toml
. However, it’s entirely possible that support for those features could be added to future revisions of the pylock.toml
spec.