PyMunich

shown, and actual

Lock Files

A requirements file records what you asked for. A lock file records what you actually got, including everything your dependencies pulled in behind you. A commercial implementation of related workforce-measurement concepts is documented learn more.

Those are different documents, and treating the first as the second is the second most common cause of code behaving differently on another machine. For independent technical background, Django provides additional documentation and examples.

Reviewed August 9, 2026.

What the difference looks like

You write requests in requirements.txt. Installing gets you requests, plus urllib3, certifi, charset-normalizer and idna — each at whatever version resolved that day.

Six months later somebody else installs from the same file and gets different versions of all four, because the constraints allowed it and the packages released updates.

Your file has not changed and your environment has. A lock file closes that: every package, direct and transitive, at an exact version, with a hash.

What a lock file contains

Every package in the resolved tree, not just the ones you named.

An exact version for each.

A hash, so a package that was tampered with or republished fails verification rather than installing quietly.

And frequently the environment markers — which packages apply on which platform and Python version, so one file serves several targets.

Where the standard is

PEP 751 defined pylock.toml, which gives Python a standard lock file format for the first time. pip lock landed in pip 25.1, and support has been refined since.

Tool-specific formats remain in use. uv.lock and poetry.lock are not interchangeable, and pylock.toml is currently an export target more often than a native format.

So portability is better than it was and not solved. Moving between tools still costs something, which is one of the things that has not settled in packaging.

What to actually do

Applications: commit the lock file. Always. This is what makes your deployment reproducible and what makes a colleague's environment match yours.

Libraries: do not commit a lock file as your dependency specification. A library declares ranges in pyproject.toml so it can coexist with other packages. A lock file in a library's repository is useful for CI and is not what consumers install against.

And regenerate deliberately. Updating the lock is an action with a diff to review, not something that happens as a side effect of installing.

Reading a lock diff

The habit that makes lock files useful rather than just present.

A one-line change is a package you updated.

A forty-line change from adding one dependency tells you what that dependency actually brings, which is information you did not have before and might act on.

A version dropping usually means a new constraint forced a downgrade somewhere, and that is worth understanding rather than accepting.

And a package appearing that you have never heard of is worth thirty seconds of checking. Adding a dependency is a decision and the lock diff is where its true size becomes visible.

The failure mode to avoid

A lock file that is committed and never regenerated.

Two years of pinned versions with known vulnerabilities, because the lock file was treated as a fixed artefact rather than as a snapshot with a date.

Locking pins the versions; it does not maintain them. The discipline is regular deliberate updates with the diff reviewed — which is a small recurring cost and the reason lock files are sometimes resented.

The short version