I don't use venv and other tools (I use docker for this)
But here some points I found interesting comparing vanilla pip to npm (and tools listed in the article fixes it):
1. You have to manually freeze packages (instead of automatic package-lock.json)
2. Each time your install/remove package, dependant packages are not removed from freeze. You have to do it manually. (interesting link: https://github.com/jazzband/pip-tools)
3. Freeze is flat list (npm can restore tree structure)
https://python-poetry.org/ and pyproject configuration is pretty decent these days and handles all those points for you. We may be forever stuck with 2 layers in python (dep management and actual installation) where node has them merged into 1. But good tools solve that pretty well.
pip is not very comparable to npm imo because it never evolved the ability to really handle projects, create venvs on its own, create lock files, etc.
Poetry is what's most comparable and personally, i am not working in python projects that don't use poetry anymore. Whenever I work on a new one, i port it to use poetry
I also insist on poetry for any python modules or applications. If it's going to support multiple versions of python then throw pyenv in for development and cicd.
I agree and wholeheartedly recommend this blog post series.
It's something every python developer should read because if you're not using poetry for example, then you're making your development life more difficult than necessary.
Poetry still has to deal with Python's flat dependency structure which means it needs a complicated dependency resolver. This isn't a bad thing though, imo. There are pros and cons.
My intuition: a python interpreter gets one `PYTHONPATH` variable and so when I `import my_dep` in my app and another dependency also imports `my_dep`, they are resolved by the interpreter and cannot specify different source locations for `my_dep`, which I believe would be called "vendoring".
Again I am not sure if that is why Python can't support a tree or simply why it doesn't currently support a tree, I searched for a PEP explicitly defining dependency resolution but couldn't find one.
Sure, but then you lose the intentionality signal of an explicit version. Ruby gems works very nicely by not requiring version numbers but always respecting the lockfile unless you explicitly update one or more packages, so when you add a package with no version you get the latest by default, and you can easily do incremental upgrades that respect version dependencies. Later if you need to lock to a specific version you add it (ideally with a comment about why it's locked to that version) and still utilize the automatic dependency version resolution for updates.
1. You have to manually freeze packages (instead of automatic package-lock.json)
2. Each time your install/remove package, dependant packages are not removed from freeze. You have to do it manually. (interesting link: https://github.com/jazzband/pip-tools)
3. Freeze is flat list (npm can restore tree structure)