Ask HN: Why Poetry did not become a mainstream package manager for Python?
I was wondering why is it not more popular? What is holding it back? What do you think?
I was wondering why is it not more popular? What is holding it back? What do you think?
If there's no real problem with the existing tools, then people will not change their tested and trusted way of working for some fancy new tool, no matter what that new tool promises!
There's an old engineering proverb about that: if it works don't mess with it.
Is there something crucial I’m missing? I feel like package management has largely been solved in python, but I admittedly haven’t done a lot of research into what other workflows are out there.
Pip’s dependency solving strategy is not correct, especially if you install pip packages one at a time.
A real dependency solver would download the metadata for all matching versions (can be done with two seeks for a wheel but gotta run setup.py for an egg…) do an smt solve and then install the wheels.
Pip just starts installing packages, hopes for the best, sometimes backtracks, often gets stuck or does the wrong thing.
One is that the dependencies are a beast. The risk that it won't find a solution between a number of libraries that are only compatible with certain versions is high.
The other one is that ML projects themselves contain data, often large amounts of data.
For instance a "word2vec" style model might be 1 gigabyte and it might be a part of another model. (Say you turn the words to vectors then put the vectors through a CNN or RNN.) The Python packaging system might be a logically correct place to store this data (a necessary part of the the model) but it's a big file that will cause hassles if you do everything right, big hassles if you do things wrong (like compress anaconda packages with slow bzip2, use whatever algorithm that Docker uses to superamplify I/O, ...)
It is nice to pack all your "empty" models (ready to train) as python packages and maybe even your "trained models" (some data files to supplement the empty files) but it will take some iteration to make it all go smoothly.
I suspect my use cases haven't been as complicated as some of the others listed in this thread, which may be why I've never felt the need to look into poetry and others.
And plus, it's just super confusing. It's never been clear to me what the difference between pip and pip3 is. I thought pip3 was for python3 packages, but it seems like pip can also be used for python3 as well. But then sometimes it seems like if I use pip I only get the python2 version.
With npm or go get, if I install a package I know exactly where it got installed a how to mnaually remove if needed. If I install something with pip, the newly installed package goes into some mysterious directory whose location is never quite certain.
So yes, there are major problems with pip, hence why competitors are showing up like poetry.
It's pretty simple; pip3 will always be for python3, pip2 will always be for python2. pip is context dependent, for example if you are in a python2 venv, it will use py2, and vice versa.
> With npm or go get, if I install a package I know exactly where it got installed a how to mnaually remove if needed. If I install something with pip, the newly installed package goes into some mysterious directory whose location is never quite certain.
If you pip install a library, it will almost definitely be installed in pythondir/lib/site-packages, unless you have messed around with your installation
pip install "pip<22"
To check which pip is for which python:
pip --version
Pyenv is pretty great for managing multiple python versions.
pip3 is the name of the system installation of the pip executable corresponding to the python 3.x installation on linux systems (maybe Mac, too) when installed from system package managers on systems where python3 is the name of the python 3.x executable when installed from the package manager.
This is not really a pip issue, but a “how python is packaged to support side-by-side system installations” issue.
Personally, I use pipenv (manages package dependencies and sub-dependencies), pyenv (python version management), and pyenv-virtualenv (creates an isolated version of Python such as 3.8) together, in tandem, over poetry and others. Personally, I think this combination gives the best amount of versatility. This even works well with difficult installs of python packages that need to be compiled into executable software. This includes stuff that has not been recently updated.
A good guide on how to do this is here (see table comparison against poetry at the bottom of the article): https://towardsdatascience.com/python-environment-101-1d68bd...
At least that's my understanding.
To gain traction and acceptance, the offering must be several times better.
Marketing also counts.
Hence the lingering demise of python2.7: python3 didn't offer sufficient sizzle until ~3.6 or so.
For one, I think competition, there is Kenneth Reitz' pipenv and then of course conda's environment.yml. I think pipenv lost the popularity contest but somehow lead to a situation where people wondered on which horse to bet.
Conda also takes a lot of market share esp. in the machine-learning deployments while also being not a 'perfect' tool.
Pretty sure we will see more poetry in the coming years.
Last but not least Poetry sometimes also feels like a weird tool. For example, when its dumping colourful stack traces on you in case of (invalid) inputs, etc.
If pip-compile would support dev and production requirements it would still be my way to go I think.
Can you elaborate on this? I use pip-compile development.in and pip-compile production.in and both use -r base.in for shared dependencies
pip-compile production.in
then use the pinned production requirements and a dev.in to produce the dev environment.
Key point being that the dev environment needs to have the very same pinned versions for all packages that are part of the prod environment.
I also found it's insistence on doing certain things reduced my flexibility. We thought it was kind of dead for a while where there were no releases for about a year.
That said, I've generally found a rise in opinionated tooling (see: black) and that frustrated me for a while. Then i realised i can just ignore it all and still be productive with my old stack if i knew what i was doing (which i do) while people still blurt their opinions elsewhere.
It certainly was dead in that time
It supports as many separate requirements files as you want, if that's what you mean.
my primary concern poetry's development stagnating due to natural causes while many projects rely on it. switching costs are high. moving from pipenv -> poetry took me days across all my projects.
they're looking for developers, but also help with managing issues on the tracker.
i also raised the issue of them being funded. I think one possible outcome is seeing if PSF's Fiscal Sponsoree program (https://www.python.org/psf/fiscal-sponsorees/) would be a fit. Waiting to see what their maintainers say.
And more importantly, the concepts it brings will eventually become Python standards (like pyproject.toml or the lock file): https://snarky.ca/what-the-heck-is-pyproject-toml/
In my startup, I started to make sure that we allocate a small monthly budget to distribute between our open source dependencies, Poetry being one of them. It's always shocking to find how little support the projects are getting - the author of Poetry currently has 11 sponsors (with majority of those being individuals).
I avoided poetry for years because it doesn't have an option to skip the lockfile. We build images, so our dependencies are frozen anyway. (Now that we use dependabot, I'm willing to have a lockfile that's automated.)
I track Python packaging changes carefully, updating from procedural setup.py, declarative setup.cfg, versioning through setuptools-scm and now PEP517 and pyproject.toml.
But even now, Python ships with setuptools, pip and venv, and a system like poetry is not really a necessity.
But if you want convenient virtualenv management, editable installs _and_ PEP517, then you probably need poetry. I haven't found another system that can do all three.
When we decided to move away, I looked at Poetry and pip-tools. Poetry seemed too different to me, don't remember specifics, but felt like too much would need to change. All I wanted was the ability to lock package versions.
Enter pip-tools. It was really simple, felt familiar, and just worked. So, that's what we chose and it's what we use to this day.
Maybe there are more elegant or modern ways of doing this, but for my personal projects I haven't found a reason to switch to anything else.
Btw, there is also micropipenv[0] now which can consume both poetry and pipenv lockfiles and convert them to pinned down requirements.txts as generated by pip-tools.
For production code I’m more worried about minimizing surprises then elegance which means it’s really hard to replace something that works. Poetry only hit 1.0 in 12/2019, so maybe I’ll try it if the api remains stable for another few years. Contrast that to JS where we’re now on webpack 5 I think and there’s really no long term support available.
Pip apparently isn’t deterministic in its resolutions, but you can achieve determinism the same way Poetry does by creating a frozen requirements.txt if you absolutely must.
I’ve only seen dependency hell in badly designed projects, particularly ones where people use libraries to share code in an organisation (which frequently turns out poorly because maintaining libraries is harder than people think).
Poetry is also really slow. I’ve noticed on larger projects doing ‘poetry add’ takes nearly 10 minutes. This often happens when people use wildcard dependencies; for whatever reason the resolver looks through all possible version combinations, which can cause resolution to take exponentially longer than it should.
Is this Jupyter-related, one wonders?
The solution to that problem is probably to do ‘pip —-ignore-installed’ and hope for the best, because without a fundamental change to how Python loads modules no fancy package manager will help you.
It's also not that hard to work out anyway.
If you’re using pip with some ad-hoc pinning you’re just using a terrible homemade version of poetry and you’re leaving a lot on the table for no real reason.
It’s great. Use it. You won’t want to go back.
https://gist.github.com/tiran/2dec9e03c6f901814f6d1e8dad0952...
It's the other guy causing the ruckus.
Is pip freeze not solving this scenario? Or is poetry solving a different scenario?
Not trying to flame war, just not sure I’m grokking.
Let's say it's June 19th and your project exists on GitHub and you have a requirements.txt file with only `Flask==2.0.1` in it.
Now let's fast forward to October 19th and you clone the project and run a docker-compose build. You'll get Flask 2.0.1 but you might get a drastically newer version of Werkzeug, Jinja2, itsdangerous and Click because all of those dependencies are defined by Flask with the >= operator.
Suddenly you have a Docker image that's much different than what it was in June and the only thing that changed is time. This becomes a problem because now it could potentially mean running different versions in dev, CI and production.
This has bitten me in the past a few times with Werkzeug and also the Vine library with Celery where it pulled in newer versions that had backwards incompatible changes that broke my app. Things worked in the past but didn't work months in the future even when none of my top level dependencies changed.
A lock file fixes this issue and it's still necessary with Docker.
I've solved it in a slightly different way using pip directly by keeping top level deps in requirements.txt, freezing out a requirements-lock.txt file and referencing it with pip3 install using the -c flag. There's example repos at https://github.com/nickjj/docker-flask-example and https://github.com/nickjj/docker-django-example that demonstrate how it's done. It's not a 100% fool proof solution like Poetry but it works well enough where I haven't had a single issue since I started using this pattern and it mostly solves the problem.
You mean not 100% fool proof?
It is, but with the strategy above a new lock file will get generated if the requirements.txt file is newer than the lock file, so if you change 1 dependency you might get newer unexpected dependencies. This is just the limitation of how pip works without building a whole new layer of dependency tracking in (which I guess is why Poetry and similar tools exists). Fortunately in practice I'm happy with the pip solution because it's a few line shell script and hasn't been a problem yet. The important part of having the lock file is there for reproduceable builds today and in the future.
There are some ways around it. For example, build an independent cache of metadata to use instead of Pypi directly.
For discussion on the topic, see this GH issue: https://github.com/python-poetry/poetry/issues/2094#issuecom...
This is now fixed, but for most of Poetry's life, it took some tricks to work on Python 3, at least on Windows; the workaround wasn't documented. So, it'd always assume Python 2. I can't remember the details, but tried and quit Poetry several times during its early life for this reason.
I use it all the time because otherwise I’d have to write my own build system.
I am not sure if poetry’s approach to solving dependencies is really correct (Personally I like downloading the metadata for the projects, SMT solving, choosing a set of wheels and installing them together. It only works for wheels since you can’t extract the dependencies for eggs w/o running setup.py)
Pip is almost right if you install all deps at once but it can’t update wrong versions of old packages incompatible with new ones you add.
Practically poetry handles cases that pip doesn’t.
My beef(s) with poetry are:
A. It is bad hygiene to copy files by default into your package; they should quit pulling wings off angels and just make a /src dir.
B. Poetry itself gets corrupted and fails to update. Delete and reinstall always gets me back on the road but I was anxious about it at first.For libraries and OpenSource that I’m building actual packages for, Poetry seems nicer to me than setup.py. I’m trying it out now with one, partly to adopt the newer pyproject.toml thing.
Packaging has always been kind of an ever changing mess in Python vs newer ecosystems, and I don’t see an end to that.
I’d just do what works best for you.
Also, the general opinionated aggressiveness of the maintainer/project is a little off putting to me. Its a little weird in the community.
Normally projects don’t dog other projects on their page. Often they cite alternatives with maybe a statement on how the philosophies vary.
But that’s just my opinion and experience. I’m sure others differ.
It cannot replace all setup.py use cases, but for pure python packages it can replace it completely.
One gripe with pyproject.toml is that I can’t do editable installs (i.e ‘pip install -e path/to/package/‘) with it. Highly annoying when trying to patch packages.
[tool.poetry.dependencies] my-package = { "path" = "path/to/package", develop = true }
This way you can patch my-package and poetry will always install the latest state of it.
I did not continue with it. Maybe the documentation was not written "to my tastes". I don't know how "mainstream" it is, but I suppose if it's initial taste has been better, I'd have stuck with it. I suspect there are others in my position, and hence, maybe it didn't take off as well as it could have.??
I’m a casual Python user btw.
However, I also maintain a number of packages with c extensions or other compiled components, and poetry has no documented way of building packages with binary components, it can only create non-any wheels.
The main problem for me is pipenv and pip doesn't solve dependencies version issues when you want to upgrade one or several packages. Poetry in the other hand never had an issue.
pip install -r requirements.dev, reference requirements.txt in it. It will install dev packages and the main ones.
Glyph† pointed out that, in Python, as an OOP language, we should objectify all the things, e.g. like what Pathlib does for file/path manipulation. (Pathlib was inspired or extracted from Twisted, IIRC.)
A Pythonic dependency/package manager library would be soooo cooool...
† https://en.wikipedia.org/wiki/Glyph_Lefkowitz https://glyph.twistedmatrix.com/
Conferences are regulated with always the same speakers who have no incentives to change their slide decks. Advising people about the broken packaging system is also a good source of income.
As someone else has said here, it's an authoritarian club.
My current organization had adopted poetry before I arrived, and I eventually had to decide that we're reversing from poetry, back to pip and explicit usage of setuptools. It was too problematic, and was costing us in production DLL-hell bugs. The solver does not allow you to pin a constraint if it conflicts with the packaging metadata of your dependencies.
The stance of the poetry team is that any discrepancies should be fixed in upstream dependency. Hey, I love purity and platonic solids too, but... so that's not a completely crazy design decision, but we're in an NP problem here. That stance requires the cooperation of every single upstream package maintainer, which obviously, no one can actually operationalize. Here is a very old issue about this:
https://github.com/python-poetry/poetry/issues/697#issuecomm...
There is some movement, and acknowledgment that a tool is useless if you can't take it full-stack for your application. As of writing, the state of the art is to fork and patch things like fastapi and flask. That's nuts. I can make our stack work with the tested tools much more consistently, and there isn't much downside.
https://github.com/python-poetry/poetry/issues/697#issuecomm...
To me, that removes the value of using poetry. `poetry install <x>` is something you do very rarely. Propping up new python environments needs to happen very frequently. The convenience doesn't outweigh the operational costs.
tl;dr: I think poetry is really cool, and it looks like npm to a developer. It doesn't play nice with others, and that's by design. For production use, pip/setuptools solves more problems than people think it does. Sure, constraints.txt is a blunderbuss for a dependency resolver. However, it works. Especially if you are making more than one package for a real-world application. If you are maintaining a standalone library without complex dependencies, sure, go for it :)
They did mess up the python 2/3 and imho they just don't want to deal with such things anymore.
Deprecating stuff is necessary as well as it is necessary to provide an upgrade path (both documentation and tooling) and new stuff.
In what way were you being forced to use tox?
python3 setup.py -q pytest
All now report WARNING: Testing via this command is deprecated and will be removed in a future
version. Users looking for a generic test entry point independent of test runner
are encouraged to use tox.
I asked a question on SO asking for non-tox alternatives, one of the tox devs replied python setup.py provisions dependencies, however, the way
it does it is considered deprecated and unsupported going
ahead. Instead, users are encouraged to use tox or ensure
their own dependencies. There's no way around that unless
you're willing to fork setuptools, fix the provision issues
and use that.The incurable optimist in me thinks that there is a set of best practices that are emerging across multiple languages, that there is a "right way to do it" that we're converging on. Poetry seems far closer to that correct approach than anything else I've tried in Python and I hope that means it will have some longevity.
The realist in me expects that some time in the next few years there will be another new hotness I'll have to decide whether to migrate all my stuff to.
python - m pytest
in an environment with all dependencies installed, or pytest
In an environment with the package itself installed.Tox automatizes the process of creating such environments.
Just out of curiosity, what exactly is your problem with tox?
I'd like to see a harmonization of packaging for 3.11.
Of course, the vibe is not strong enough for me to exit the peanut gallery and contribute, so maybe we should be thankful for what we have from the thousands of human-years already invested.