A list of currently installed packages in the current environment, with their exact versions. This is only the actually needed packages, with their transitive dependencies, unless you've left something behind from earlier in development. If you're keeping abstract dependencies up to date in `pyproject.toml` (which you need to do anyway to build and release the project), you can straightforwardly re-create the environment from that list and freeze whatever solution you get (after testing).
Doesn’t account for differences in platforms or Python versions, and doesn’t contain resolved dependency hashes.
So it’s a “lockfile” in the strictest, most useless definition: only works on the exact same Python version, on my machine, assuming no dependencies have published new packages.
Look, I'm not trying to sell this as a full solution - I'm just trying to establish that a lot of people really don't need a full solution.
>only works on the exact same Python version
It works on any Python version that all of the dependencies work on. But also it can be worked around with environment markers, if you really can support multiple Python versions but need a different set of dependencies for each.
In practical cases you don't need anything like a full (python-version x dependency) version matrix. For example, many projects want to use `tomllib` from the standard library in Python 3.11, but don't want to drop support for earlier Python because everything else still works fine with the same dependency packages for all currently supported Python versions. So they follow the steps in the tomli README (https://github.com/hukkin/tomli?tab=readme-ov-file#building-...).
>on my machine
(Elsewhere in the thread, people were trying to sell me on lock files for library development, to use specifically on my machine while releasing code that doesn't pin the dependencies.)
If my code works with a given version of a dependency on my machine, with the wheel pre-built for my machine, there is no good reason why my code wouldn't work on your machine with the same version of the dependency, with the analogous wheel - assuming it exists in the first place. It was built from the same codebase. (If not, you're stuck building from source, or may be completely out of luck. A lockfile can't fix that; you can't specify a build artifact that doesn't exist.)
This is also only relevant for projects that include non-Python code that requires a build step, of course.
>assuming no dependencies have published new packages.
PyPI doesn't allow you to replace the package for the same version. That's why there are packages up there with `.post0` etc. suffixes on their version numbers. But yes, there are users who require this sort of thing, which is why PEP 751 is in the works.
So many misunderstandings here :/ I can’t muster the energy to correct them past these two obvious ones
> It works on any Python version that all of the dependencies work on
No, it doesn’t. It’s not a lockfile: it’s a snapshot of the dependencies you have installed.
The dependencies you have installed depend on the Python version and your OS. The obvious case would be requiring a Linux-only dependency on… Linux, or a package only required on Python <=3.10 while you’re on 3.11.
> PyPI doesn't allow you to replace the package for the same version
Yes and no. You can continue to upload new wheels (or a sdist) long after a package version is initially released.
I've spent most of the last two years making myself an expert on the topic of Python packaging. You can see this through the rest of the thread.
>No, it doesn’t. It’s not a lockfile: it’s a snapshot of the dependencies you have installed.
Yes, it does. It's a snapshot of the dependencies that you have installed. For each of those dependencies, there is some set of Python versions it supports. Collectively, the packages will work on the intersection of those sets of Python versions. (Because, for those Python versions, it will be possible to obtain working copies of each dependency at the specified version number.)
Which is what I said.
> The dependencies you have installed depend on the Python version and your OS. The obvious case would be requiring a Linux-only dependency on… Linux, or a package only required on Python <=3.10 while you’re on 3.11.
A huge amount of packages are pure Python and work on a wide range of Python versions and have no OS dependency. In general, packages may have such restrictions, but do not necessarily. I know this because I've seen my own code working on a wide range of Python versions without making any particular effort to ensure that. It's policy for many popular packages to ensure they support all Python versions currently supported by the core Python dev team.
Looking beyond pure Python - if I depend on `numpy==2.2.1` (the most recent version at time of writing), that supports Python 3.10 through 3.13. As long as my other dependencies (and the code itself) don't impose further restrictions, the package will install on any of those Python versions. If you install my project on a different operating system, you may get a different wheel for version 2.2.1 of NumPy (the one that's appropriate for your system), but the code will still work. Because I tested it with version 2.2.1 of NumPy on my machine, and version 2.2.1 of Numpy on your machine (compiled for your machine) provides the same interface to my Python code, with the same semantics.
I'm not providing you with the wheel, so it doesn't matter that the wheel I install wouldn't work for you. I'm providing you(r copy of Pip) with the package name and version number; Pip takes care of the rest.
>You can continue to upload new wheels (or a sdist) long after a package version is initially released.
Sure, but that doesn't harm compatibility. In fact, I would be doing it specifically to improve compatibility. It wouldn't change what Pip chooses for your system, unless it's a better match for your system than previously available.
Holy hell dude, you don’t need to write a novel for every reply. It’s not a lockfile because it’s a snapshot of what you have installed. End of.
It doesn’t handle environment markers nor is it reproducible. Given any non-trivial set of dependencies and/or more than 1 platform, it will lead to confusing issues.
Those confusing issues are the reason for lock files to exist, and the reason they are not just “the output of pip freeze”.
But you know this, given your two years of extensive expert study. Which I see very little evidence of.
>It’s not a lockfile because it’s a snapshot of what you have installed.
I didn't say it was. I said that it solves the problems that many people mistakenly think they need a lockfile for.
(To be clear: did you notice that I am not the person who originally said "'pip freeze' generates a lockfile."?)
>It doesn’t handle environment markers nor is it reproducible.
You can write environment markers in it (of course you won't get them from `pip freeze`) and Pip will respect them. And there are plenty of cases where no environment markers are applicable anyway.
It's perfectly reproducible insofar as you get the exact specified version of every dependency, including transitive dependencies.
>Given any non-trivial set of dependencies and/or more than 1 platform, it will lead to confusing issues.
Given more than 1 platform, with differences that actually matter (i.e. not pure-Python dependencies), you cannot use a lockfile, unless you specify to build everything from source. Because otherwise a lockfile would specify wheels as exact files with their hashes that were pre-built for one platform and will not work on the others.
Anyway, feel free to show a minimal reproducible example of the confusion you have in mind.
> Given more than 1 platform, with differences that actually matter (i.e. not pure-Python dependencies), you cannot use a lockfile, unless you specify to build everything from source. Because otherwise a lockfile would specify wheels as exact files with their hashes that were pre-built for one platform and will not work on the others.
What is more likely:
1. Using a lockfile means you cannot use wheels and have to build from source
2. You don’t know what you’re talking about
(When deciding, keep in mind that every single lockfile consuming and producing tool works fine with wheels)