Freezing Requirements with Pip-Tools
til.simonwillison.net
til.simonwillison.net
What are we using now? Pip? Pyenv? Pipenv? Poetry? Hatch? Conda?
Once that's settled, there's invariable some library that has some native buildchain tooling requirement that isn't satisfied and the build process has shat all over my terminal. So now I have to hunt down whatever libraries gcc is complaining about.
Christ, it should be against the law to release a programming language that doesn't have dependency management built-in.
Of course, for standard package installation.
> Pyenv?
Yes, if you need multiple Python versions available on the same system.
> Pipenv?
God no. https://chriswarrick.com/blog/2018/07/17/pipenv-promises-a-l...
> Poetry? Hatch?
Yes, for local environment management and library dependency configuration.
> Conda?
Not really, unless you're doing data science and are heavily invested in the rest of Anaconda ecosystem.
I don't really understand where the confusion is coming from - Python is used in a wide number of use cases and scenarios, and it is no surprise that there are many different tools in the box, each solving a different subset of problems.
The packaging issue has been all but resolved in recent years, with the advent of wheels, pyproject.toml and a number of other standards.
> So now I have to hunt down whatever libraries gcc is complaining about.
Which has nothing to do with Python.
It is a great tool that I use in all my projects. It effectively solves dependency management for me in a very easy to use way.
Dependency management using requirements.txt used to give me such a headache, now I just have a pyproject.toml that I know works.
[tool.poetry.dependencies]
python = ">=3.8,<3.9"
pandas = "^1.4.3"
This basically means: Use the version of python between 3.8 and 3.9 and use any version higher than 1.4.3 for pandas.What I like about poetry is that it makes sure that the whole dependency graph of the packages that you add is correct. If it can not solve the graph, then it fails fast and it fails hard, which is a good thing.
This is probably a very bad explainer of what poetry does, but be sure to check it out! :)
The related issue, https://github.com/python-poetry/poetry/issues/496, has been open for 4 years with no movement.
The other issue with Poetry is that it uses its own pyproject.toml dependency listing format instead of the one standardized in the relevant PEP (https://peps.python.org/pep-0621/). This is understandable for historical reasons (Poetry was first written before this was standardized), but Poetry should have been updated to support the standard format.
A relatively minor issue, but the poetry shell command is also a footgun. It's presented as a way to configure your shell to activate the virtualenv for the project. In reality it's a very slow, barely functional terminal emulator running on top of your terminal, which will cause problems for any programs that assume a working terminal or talk to the tty directly.
poetry shell is also not a term emulator, it's just a subshell with some environment variables setup for your project. Once you are in, it's just a regular shell. If anything is slow, it's where you add or remove a dependency, but it's probably faster than you editing requirements.txt, clearing out your virtualenv and then reinstalling everything again.
The process spawned by `poetry shell` is a terminal emulator driven by the pexpect and cleo packages. It hijacks and proxies the user's keystrokes before sending them to the underlying terminal.
A terminal emulator will be something substantially more complex such as libvterm. If it ain't handling terminfo, it ain't a terminal emulator.
Direnv is better, direnv layout will automatically create a hidden virtualenv directory on your work tree and sets up your path when you cd into it. The only downside is it doesn't seem to work on Windows.
cd /your/project && echo "layout python" > .envrc && direnv allow
Give it a go then tell me what the point is for any of these poetry/pipenv/hatch/flit/pdm/pyflow thingy if neither you or your teammates work on Windows.The main reason to use poetry is sane dependency management the way it exists for most other ecosystems (bundler, cargo, npm, maven, gradle, ...). In particular, that includes lockfiles.
Use pyenv to install all the different python versions you need.
Ideally, all of these functionality should bundled in one tool, but the only thing that's available is pyflow, which don't stop blowing up with an exception for me.
How you install multiple Python versions doesn't really matter as long as the binaries are on your PATH. You can use Homebrew or Macports or Pyenv or whatever. The only remaining problem is how to manage your virtualenvs. You can use virtualenv or venv directly, but you will have to manage where to put them and remember to activate them before you install dependencies and dev tooling. But if you use direnv, it's fire and forget, once you have direnv setup and one line of directive in a .envrc file, or perhaps a few gitignore, you don't have to think about where to put the virtualenv or remember to activate it again.
So yes, I'm actually just recommending direnv if you want to keep it simple.
I really disagree, and I think so does everyone who uses Poetry, pipenv, pip-tools, etc.
You can also constrain the Python version in there if you want.
[1] https://setuptools.pypa.io/en/latest/userguide/quickstart.ht...
Using a tool specific config file seems like a design choice with upsides and downsides, which I respect
Can a requirements.txt or a Pipfile store cryptographically-signed hashes for each dependency? Which tool would check that not PyPI-upload but package-builder-signing keys validate?
FWIU, nobody ever added GPG .asc signature support to Pip? What keys would it trust for which package? Should twine download after upload and check the publisher and PyPI-upload signatures?
Only if the key used to sign the package / package manifest with per-file hashes is or was retrieved over a different channel (i.e. WKD, HKP (HTTPS w/w/o Certificate Pinning (*))), and the key is trusted to sign for that package, then install the software package artifact and assign file permissions and extended filesystem attributes.
> sigstore empowers software developers to securely sign software artifacts such as release files, container images, binaries, bill of material manifests [SBOM] and more. Signing materials are then stored in a tamper-resistant public log.
/? sigstore sbom: https://www.google.com/search?q=sigstore+sbom
> It’s free to use for all developers and software providers, with sigstore’s code and operational tooling being 100% open source, and everything maintained and developed by the sigstore community.
> How sigstore works: Using Fulcio, sigstore requests a certificate from our root Certificate Authority (CA). This checks you are who you say you are using OpenID Connect, which looks at your email address to prove you’re the author. Fulcio grants a time-stamped certificate, a way to say you’re signed in and that it’s you.
https://github.com/sigstore/fulcio
> You don’t have to do anything with keys yourself, and sigstore never obtains your private key. The public key that Cosign creates gets bound to your certificate, and the signing details get stored in sigstore’s trust root, the deeper layer of keys and trustees and what we use to check authenticity.
https://github.com/sigstore/cosign
> our certificate then comes back to sigstore, where sigstore exchanges keys, asserts your identity and signs everything off. The signature contains the hash itself, public key, signature content and the time stamp. This all gets uploaded to a Rekor transparency log, so anyone can check that what you’ve put out there went through all the checks needed to be authentic.
In comparison to poetry I think it includes more advanced multi-environment and multi-python-version support and a tox-like testing matrix. It probably gets a little too complex there.
It also works with pyproject.toml
If anyone else has experience with Hatch vs Poetry please share!
https://hatch.pypa.io/latest/meta/faq/#libraries-vs-applicat...
As does pip these days.
https://direnv.net/man/direnv-stdlib.1.html#codelayout-pytho...
That said, I've used both pipenv and poetry, and I had projects where pipenv would simply time out when trying to resolve packages. I haven't seen the same behaviour with poetry (indeed, that was the reason I migrated one project from pipenv to poetry after I just had to give up with the former).
Our production environment was python3.6. Devs rebuilt the requirements.txt with python3.8.
When we attempted to use the requirements.txt with python3.6, we couldn't because a package was missing (and we installed with `--require-hashes`). The dependency was `importlib-metadata` iirc.
But googling around, here's an example of a package that has dependencies that changed based on the python version: https://github.com/pypa/pep517/blob/main/pyproject.toml#L13 .
In our case, we just made sure to rebuild the requirements.txt with the version that matched our production; not sure if there's a "nice" way to support multiple versions with pip-tools.
I might be splitting hairs here, but this seems like an oxymoron: if it's agnostic on anything, it's not really a lock file.
If you don't want to fire up docker, you'll have to look elsewhere other than just pip-tool
https://github.com/jazzband/pip-tools/issues/1167
I personally find it extremely useful when upgrading dependencies.
poetry is alright but it doesn't support the latest PEP standards, and its slow.
PDM is where it's at; it's fast, has a really responsive maintainer, supports all the latest PEP standards, and has really good cross-platform support.
pdm.fming.dev/
https://twitter.com/mkennedy/status/1375242144135270403?lang...
pip-tools was never advertised as well as poetry or pipenv, despite in my opinion being a better tool for the job, and having a best-in-class dependency resolver.
I don't think this is true. Pipenv and poetry's feature set largely coincides with the feature set of similar tools in other languages (e.g. bundler, cargo). Some such tools have even larger feature sets (e.g. maven, gradle). Nonetheless, these tools haven't lost out to "smaller tools", but have become standard tools in their respective communities.
The problem in the Python ecosystem is fragmentation. Nobody can agree on what the right tool for the job is, so everyone uses something different, dependencies/projects don't always work well with all tools, etc.