[HN Gopher] How to improve Python packaging ___________________________________________________________________ How to improve Python packaging Author : Kwpolska Score : 146 points Date : 2023-01-15 16:27 UTC (6 hours ago) (HTM) web link (chriswarrick.com) (TXT) w3m dump (chriswarrick.com) | Lyngbakr wrote: | It seems most people agree that Python's packaging isn't great, | but, conversely, is there a language where most people agree that | the approach to packaging is awesome? I mean, what's the gold | standard to aspire to? | nixpulvis wrote: | Ruby gems and Cargo are pretty awesome. Also, I find I like | Arch linux's Pacman quite a bit, though that's a slightly | different use case where versioning isn't resolved. | oconnor663 wrote: | Cargo is a gold standard imho, but there are definitely some | simplifying decisions it makes that might not fit Python: | | - Dependencies and executables can run arbitrary code during | build. For example, Cargo knows almost nothing about how to | build C code, and the common workflow is to pull in the | popular `cc` library for this and call it in your build.rs. | | - There's mostly no such thing as "installing a library", and | each project builds its dependencies from source. This is | baked in at the Cargo level (the install command just doesn't | work for library crates) and also at the language level (no | stable ABI besides "extern C"). | | - Related to that, the final product of a Cargo workflow is a | mostly-statically-linked binary, so there isn't really an | equivalent to virtualenv. | Kwpolska wrote: | > - Dependencies and executables can run arbitrary code | during build. For example, Cargo knows almost nothing about | how to build C code, and the common workflow is to pull in | the popular `cc` library for this and call it in your | build.rs. | | Python packaging involves arbitrary code execution, even | today. While it's less obvious than it was with `setup.py`, | if you're installing from source, the package can specify | any build backend it wants, and that build backend can do | anything. This could be mitigated by having an allowlist of | build backends, but who would be responsible for vetting | the tools, and how would it be guaranteed that an allowed | tool is not taken over by someone hostile, and that an | allowed tool does not have a system to run arbitrary | package-provided code? | earthling8118 wrote: | I don't think the final build output being statically | linked has any connection to a virtualenv. I've only ever | used Python's virtualenvs to avoid having to install | dependencies globally. When using Cargo you don't need to | worry about that because their data is saved per-project | already and Cargo can sort itself out when you invole a | command | orhmeh09 wrote: | R with CRAN. renv for reproducibility | gen220 wrote: | I think Go (if you started using it in the `go mod` era) and | Rust have the best stories around package management. | | The interface around `go mod` is kind of confusing, but I have | actual trust in the dependency graph it generates for me. Cargo | has, afaict, nailed both the interface and trust in what's | going on under-the-hood. | | In the Python world, Poetry isn't too bad. It's terribly slow | in comparison to `go mod` or Cargo, but I generally trust and | understand what's happening on the inside, and it's interface | is fairly legible to newcomers. | TheChaplain wrote: | Don't know if it counts but Java has done pretty well in my | opinion. A single JAR-file can combine everything you need to | run an application or be distributed as a library, and as long | as the java command is installed it just works. | | Likewise WAR's make it dead simple to add/remove/update | applications during runtime. | | Of course there are always special cases, but packaging and | distribution in the Java world have always been painless to me. | neillyons wrote: | I'm a big fan of `mix` for Elixir. | https://hexdocs.pm/mix/Mix.html | di4na wrote: | This. Mix is basically a mix (pun unintended) of Leiningen | and Bundler. It works. Quite well. | | Part of this is due to erlang solving a lot of the problems | upfront (releases) and then the Hex team handling a lot of | the rest. | | But in general, the "Yehuda Katz" lineage (Bundler, Cargo, | Yarn v1, mix as Jose used to be mentored by Yehuda) have | pretty good tools worth copying. At least as a base. | Kwpolska wrote: | I don't think there's much complaining in the C#/.NET | ecosystem. Sure, there are alternate tools (FAKE for F#), but I | believe most people are happy enough with | dotnet.exe/msbuild/nuget. | DangitBobby wrote: | I think this is what success for unification looks like: | | Let's say there are two tools, one called pyup and one called | pygo. pyup: responsible for which versions of | python are available on your machine, as well as | which one is the default "system" python. It also keeps itself | and pygo updated. pygo: responsible for (among | other things) - allowing a user to specify a | python version for a project - allowing a user to | specify a python version for a script - helping | the user install a compatible python version for the project | with pyup - helping the user install a compatible | python version for a script with pyup - selecting | a compatible python version/env for project - | selection a compatible python version/env for a script | - allowing a user to specify project dependencies | - allowing a user to specify script dependencies within a | script - determining which dependencies are | required for a project - determining which | dependencies are required for a script - | installing project dependencies - installing | script dependencies - installing projects or | scripts as executables | | I MUST NOT need a base python install to make any of this work. | Tools are constantly mucking with system python and which one | is on my path so I can't trust system python, period. pyup and | pygo should be their own binaries which invoke python. | example.py: #!/usr/bin/env pygo # | version: ~3.11 # requirements: # requests~=2 | import requests requests.get("https://example.com") | | When I run ./example.py for the first time: - | pygo helps me install python 3.11 - pygo installs | requests in a location that I don't have to worry about | | When I run ./example.py for the second time, the script runs | without error. | | If I still need to use something like virtualenv, poetry, or | conda on top of this, the unification project has failed. | korijn wrote: | I get the impression the author has not been exposed to enough | pain doing package maintenance on a webpack codebase. | mkoubaa wrote: | I use sites as composable mini venvs, but there's no tooling for | that | Spivak wrote: | Not being able to exclude system packages from resolution when | using __pypackages__ is a pretty glaring omission that will force | people to continue using venvs until it's fixed. | [deleted] | tiziano88 wrote: | Interesting article though it's missing at least a mention of | Nix, which IMO solves a lot of the pain points described. | charliermarsh wrote: | It's interesting to note that PEP 582 (i.e. __pypackages__) mode | used to be the PDM default -- and was sort of its flagship | feature -- before being made opt-in with 2.0 release, the | explanation being that the PEP had stalled, and that editor and | IDE support for virtualenvs is much better | (https://www.pythonbynight.com/blog/using-pdm-for-your- | next-p...). | | If you read through the discussion on the Python forum, one of | the counterarguments to the PEP is that "If existing tools can | already support this, why do we need a PEP for it?" But | presumedly a PEP would help push the ecosystem to accommodate | __pypackages__, and to solve the aforementioned problems (like | broader editor and IDE support). | | For what it's worth (as someone that builds Python tooling full- | time): I'm generally a fan of moving to a node_modules-like | model. | charliermarsh wrote: | Oh, also, I think I've read the entire Discussions thread on | this PEP, and from what I can tell, the PEP is missing | champions who are eager to push it forward. | | Part of the problem, I'm guessing, is that the PEP kind of sits | in a weird space, because it's not up to the PyPA to "approve" | it, or whatever -- PEPs are approved by the Python Steering | Council. | | Per Brett Cannon (Steering Council Member): | | > Either consensus has to be reached (which it hasn't) and/or | someone needs to send this to the SC to make a decision | (although it is a weird PEP in that it also impacts packaging, | so it isn't even clear who would get final say). | | https://discuss.python.org/t/pep-582-python-local-packages-d... | Kwpolska wrote: | That tooling argument is quite weak. PDM is the only tool I was | able to find that has support for __pypackages__, the paths it | uses seem to be slightly different to the PEP wording, and it | uses a $PYTHONPATH/shell hack (`pdm --pep582` adds a folder | with `sitecustomize.py` that does the magic). How do you change | the $PYTHONPATH used by an IDE (and its magic features)? | charliermarsh wrote: | I agree! | smitty1e wrote: | Time for GvR to saddle up the BDFL pony for a (last?) ride? | dataflow wrote: | Regarding system package upgrades breaking virtual environments: | would hard links address this? If the system package manager | removes a file, your venv still has a hard link to it so it | doesn't see a difference. | Denvercoder9 wrote: | It would also prevent the Python in your venv from receiving | any updates when the system-wide Python is installed. At that | point it's probably easier to just use your own Python | installation, e.g. with pyenv. | dataflow wrote: | Sure but installing a new copy would defeat the space | savings. The goal of this was to get the desired effect | without wasting as much space. I wasn't trying to optimize | purely for ease of use. | | Put another way, my suggestion was to migrate from symbolic | links to hard links. | arunkant wrote: | One more thing we need is app distribution for desktop apps | written in python. I need to be able to package python app as | single binary. There are tools like pyoxidizer | https://pyoxidizer.readthedocs.io/en/stable/ . hopefully it | become standard in python community | ctoth wrote: | You probably already know about this, but Nuitka[0] is pretty | great for building distributable Python apps. | | [0]: https://nuitka.net | egberts1 wrote: | What is clearly still missing on python.org website is the | obvious edit-code-run-debug step-by-step HOWTO for a typical | tight but circular Python development iterations, complete with | standardized packaging approach. | rektide wrote: | Cant resist digging at Node.js even when writing up how | infinitely better Node.js is at dealing with packages than | python, haha: | | > _Let's try removing is-odd to demonstrate how badly designed | this package is:_ | | You literally just deleted _is-even_ 's dependency on _is-odd_ | then have the audacity to be shocked that it broke? | | There's a lot of hatred for the _small package_ philosophy of | node.js, but it 's also a huge win, stands a good chance of being | why javascript has been such a winner, gotten so far: very | explicit small things that say what they do on the tin. Rather | than repeat yourself by making a copy pasted _is-even_ and then | maintaining both, it makes perfect sense to compose | functionality, to build off what we have. And it is easier to | understand the scope of what a package is & what it can do when | it is explicitly limited in scope. | | This is another place where there is lots of loud vociferous | animosity against what is, but it's there for good reason. And | with rare rare exception- left-pad rage-quit deliberate breakage, | for example, it serves well. With the exception that yes, | inventorying your stuff is hard. | Kwpolska wrote: | There's a place for small packages, but is-even/is-odd is a bit | too small to be a reasonable package. It is far easier to just | write `x % 2 === 0` inline, which is an obvious idiom, instead | of installing and importing a separate package for this. The | use of is-odd by is-even can be confusing for users. For | example, you may call isEven(0.5) and get the following error: | | RangeError: is-odd expects an integer. at isOdd | (/tmp/mynodeproject/node_modules/is-odd/index.js:17:11) at | isEven (/tmp/mynodeproject/node_modules/is-even/index.js:13:11) | at Object.<anonymous> (/tmp/mynodeproject/index.js:3:13) | | (But the main point of the demonstration was to showcase | dependency resolution and where it looks for packages.) | rektide wrote: | isEven is in thay stack trace - should not confuse anyone | with even a basic introductory level fluency at coding. | | Is it too small? What if latter the language evolves BigInt? | Donwe suffer a patchwork of libraries which have & havent | upgraded, sussing around each time to find out? | | I think the key thing to recognize is that this is all | opinion. Many people dont like the availability of many | opions, the ease at which dependencies have grown. And that's | fine, there's some real pain here to having ballooning | package trees. There's a pevel of conceit though that I feel | that often arises, where we mock & shiv packages like _is- | even_ . But to me, it 's not absolute, it's a matter of taste | & preference. It looks weird to outsiders, but it has been | enormously powerful & helpful, has been such a key successful | element of JS that npm arose & made package management easy & | package publishing easy & that we begat a new behavior of | capturing all the little helpful things we do & making them | available. | | Maybe there are good reasons for inlining simple things, but | it's not clear to me what the gains really are, or what's | wrong with is-even. | zdragnar wrote: | It would be nice if major node packages invested time in re- | inventing the wheel, just a little bit. | | Back when I used it, I really appreciated how little bloat Hapi | added to node modules, compared with webpack for example. | | Obviously there's a world of difference in what problems the | two solve, but still... | kdazzle wrote: | I'm biased, but I do like Python's package management much | better than Node. Even just regular old virtualenvs. Can't tell | you how many times deleting the node packages dir and | reinstalling fixes a weird issue, but that's happened very | rarely for me on the python side. | | Also, having to comb through a bunch of node packages of | dubious quality to find some sort of standard approach happens | way too often. Like take python requests vs axios. | phailhaus wrote: | I'd say that Node's package management has run laps around | Python's, to the point where it's pretty embarrassing. Since | it's relatively new, it was able to hit the ground running | with best practices: | | 1. Declarative package manifests. Python's ecosystem is still | a mess of various approaches, and the fact that you have to | _run the setup.py script_ to determine dependencies is a | nightmare. Because of this, running dependency resolution and | installing is an order of magnitude faster in Node than in | Python. | | 2. Drop-dead simple isolated environments: everything's in | `node_modules`. You literally can't make a mistake by blindly | running `npm install` in the project dir. With Python it's on | you to manage your virtualenv, which boils down to PATH | manipulation and symlinks that you'll have to remember to | undo when switching around. There's no default for what to | call your venv either, so it's on you to settle on a standard | and gitignore it. Every time you run `pip install`, you have | to hesitate and make sure you're in the right environment, or | else risk borking the wrong env (or your global!) | | 3. Out-of-the-box comprehensive lockfile support. Debugging | Python dependency issues is a nightmare. There's literally no | way to figure out why a dependency was installed without | using 3rd party tools (like pipdeptree). In Node, simply | running `npm install` will automatically generate a proper | lockfile. | | I work full stack, and the difference is like night and day. | I barely think about dependency management in Node. | gen220 wrote: | Respectfully, this reads like you're using outdated Python | tools. | | Give Poetry [1] a shot, it has all the things you've listed | here. Just as Node.js has come a long way in the last 5 | years, Python has, too. Albeit, in a fashion that was much | less centralized, arguably to Python's detriment. | | [1]: https://python-poetry.org/history/#100---2019-12-12, | released 1.0 in 2019/12. | phailhaus wrote: | Oh yeah, I've used Poetry. I'm talking about Python out | of the box. The dependency management ecosystem is super | fractured and relies on 3rd party tools developing their | own standards, and even then, they can't overcome | fundamental limitations. For example, Poetry is great but | locking/installation still takes way longer than Node | because there are no declarative manifests. | revskill wrote: | I've tried with venv before, and the console (Iterm) just get | broken. | charliermarsh wrote: | > There are two tools for dealing with packages in the Node | world, namely npm and Yarn. | | Not to mention pnpm. Or Bun. Or even Deno. All of which deal with | packages, and make different choices. | | This isn't to be a pedant, but I think it's a reasonable example | of why it's less important that there's a single way to do a | thing, or even a single tool vs. multiple alternatives; instead, | what I care about is that I don't have to string together tens of | tools to do that thing, and that there's some degree of | compatibility and standardization in the API between those | different alternatives. | matsemann wrote: | Because of the insanity of python I run everything in Docker | (through compose). No more issues with it not working on some | dev's computer because of a missing wheel, or that they need to | have X and Y c++ toolchain packages installed locally etc. No | more trying to fix a broken setup after upgrading python or | poetry versions, just "docker compose build" and you're up and | running. No spending days getting a freshly cloned project up and | running. | | Then I point Pycharm to use that as my remote interpreter through | docker compose. | | Not watertight, but a hundred times better dev experience. | groestl wrote: | I secretly believe Docker only exists because of how f'up | Python's distribution story is. | jessekv wrote: | I also have often wondered how much Docker owes its success | to the shortcomings of python. | DangitBobby wrote: | I've tried this a couple of times but just generally not liked | the experience and gone back. When you get a shell into the | container so you can use your project's python env, the tools | you have installed on your machine (bashrc, rg, aliases) aren't | available. I ultimately prefer the hassle of managing | environments natively over forfeiting the use of my tools or | juggling shells. | goodpoint wrote: | No way. Docker is not designed for security. | wheelerof4te wrote: | When the solution to basic problem like this is "use Docker", | you realise how deeply flawed modern software development (in | Python, at least) is. | jessekv wrote: | Not sure I agree with "deeply flawed" verdict. | | The flaws of python's packaging system (as well as the GIL | and other hangups) emerge from the tradeoffs of inventing a | language optimised for reusing and connecting as many | disparate system binaries as possible. | | Its not surprising that such a server scripting language is | tightly coupled with the server environment that it runs in. | Docker is just one way to ensure a reproducible server | environment across machines. | | What do you think it could have done differently? | LtWorf wrote: | .deb packages... | groestl wrote: | Do you happen to have a link to a python application that | ships it's own dependencies and has state-of-the art debian | packaging? | sam345 wrote: | The main reason I have stayed away from Python. packaging is a | mess! | c7DJTLrn wrote: | And one of the reasons I moved away from it! My blog post on | the subject was posted here and it was very unpopular despite | having similar points and also making comparisons with Node. | | There's nothing special about Python that makes it worth | enduring this pain. We have other languages with a better | developer UX. | noisy_boy wrote: | conda is a bleeding pain in the ass; installed a ton of stuff | without even asking if I needed them. Then when I wanted to | install a different version of Python, kept running conflict | resolution for hours before I got tired and killed it. Might as | well just do the setup oldschool via virtualenv using | requirements.txt. | | Dealing with all this is why I chose to use golang for writing a | CLI utility (even though I'm not a big fan of its error handling | boilerplate); static typing + produces a single binary that can | be run without needing any of the environment setup. I am aware | of various Python tools that can produce a binary too but I think | they have their own edge cases and it is just nicer when that can | be done out of the box without any dependencies. | | > You can also find deficiencies in the tools for the other | languages mentioned. Some people think Maven is terrible because | it uses XML and Gradle is the way to go, and others think | Gradle's use of a Groovy-based DSL makes things much harder than | they need to be and prefer Maven instead. | | Yeah but I have never had the installer crap out like pip or its | ilk do when installing a package with maven. At worst, it can't | find the package if the repositories are not configured properly. | optimalsolver wrote: | Python packaging is a solved problem: | | https://python-poetry.org/ | revskill wrote: | Yes, there should be (one way) to do packaging. | Kwpolska wrote: | Poetry is one of the better options, but its nonstandard | pyproject.toml is not ideal. PDM is basically Poetry, with the | metadata standard in place, and with support for | __pypackages__. | c7DJTLrn wrote: | It's not really solved if you have no choice but to work with | codebases that don't use Poetry (quite common). There's 14 | tools for people to choose from that aren't going away any time | soon. | throwawaaarrgh wrote: | as a Poetry user myself, ummmmmmm. no. lol | [deleted] | josteink wrote: | Every time someone asks me what I think is wrong with Python | packaging, I'll show them this link. | | Saved. Thanks for sharing! | woodruffw wrote: | It's not very well documented, but the PyPA tools _do_ provide a | unified experience when used correctly. | | Here's a PyPA project (FD: one I work on) that uses a single | pyproject.toml to handle all aspects of packaging (and most non- | packaging tool configuration, to boot)[1]. With a single file | like that, the _only_ thing you need to do to start a local | development environment is: python -m venv env | && . env/bin/activate python -m pip install .[dev] | | (We provide a `make dev` target that does that for you as well.) | | Similarly, to build distributions, all you need is `build`: | python -m build | | [1]: https://github.com/pypa/pip-audit | Denvercoder9 wrote: | That repository doesn't seem to pin dependency versions. How do | you integrate that in this workflow? | woodruffw wrote: | You could use `pip-compile` if you want full pinning. That's | what we do on another project -- we use GitHub Actions with | `pip-compile` to provide a fully frozen copy of the | dependency tree for users who'd like that[1]. | | In the context of `pip-audit`, that makes a little less | sense: most of our dependencies are semantically versioned, | and we'd rather users receive patches and fixes to our | subdependencies automatically, rather than having to wait for | us to release a corresponding fix version. Similarly, we | expect users to install `pip-audit` into pre-existing virtual | environments, meaning that excessive pinning will produce | overly conservative dependency conflict errors. | | [1]: https://github.com/sigstore/sigstore- | python/tree/main/instal... | Izkata wrote: | Or if you don't want to install something else and are | willing to just use version numbers (instead of also hashes | like pip-compile in that link), "pip freeze" is built in. | woodruffw wrote: | The tricky thing with `pip freeze` is that it dumps your | _environment_ , not your _resolved set_ : your | environment also contains things like your `pip` and | `setuptools` versions, any developing tooling you have, | and potentially your global environmental state (if the | environment has global access and you forget to pass | `--local` to `pip freeze`). | | In other words, it's generally a superset of the | resolutions collected by `pip-compile`. This may or may | not be what you want, or what your users expect! | Izkata wrote: | By default (at least in python3 nowadays) it also | excludes pip, setuptools, distribute, and wheel; you need | "--all" to include them in the output. | woodruffw wrote: | Oh, that's news to me! I stand corrected. | | (The point about other development tooling is, I believe, | still accurate -- if you e.g. have `black` installed, | `pip freeze` will show it.) | fbdab103 wrote: | Which is a huge limitation of many of the other tools. I | have some beef with poetry, but it did at least get one | thing correct: differentiating between the code required | libraries and the development tooling (pytest, black, | etc). There are hacky workarounds to accomplish this with | other tools, but codifying this differentiation is | incredibly valuable. | lmm wrote: | That's still about 4 times as much command as I'd consider | normal/reasonable, compared to say "mvn install". | qbasic_forever wrote: | Nowhere in pypa documentation is your simple workflow described | or mentioned. Instead it's a jumble of links to a myriad of | tools including hatchling, flit, pdm, etc. and basically just a | shoulder shrug, 'I don't know, figure it all out yourself' | message. This article makes a great point that the current pypa | 'guidance' is too confusing and vague for actual end users | (i.e. people that don't work directly on pypa or haven't been | studying python packaging for decades). | woodruffw wrote: | I agree that it's confusing. That being said, there is an | official PyPA tutorial that goes through the exact steps need | to produce the commands I suggested, so I don't think it's | accurate to say that it's nowhere to be found[1]. | | Edit: Unfortunately it's easy to confuse the above tutorial | with this one[2], which is specifically for setuptools. So I | can appreciate end user confusion around the documentation, | particularly in that respect! | | [1]: https://packaging.python.org/en/latest/tutorials/packagi | ng-p... | | [2]: https://packaging.python.org/en/latest/guides/distributi | ng-p... | qbasic_forever wrote: | No I'm looking at link 1 and specifically have an issue | with the huge table of options for how to setup your | pyproject.toml--it has tabs for hatchling, flit, pdm, etc. | but _zero_ description of why I would want to use one of | those tools. It's just more confusing, like you're being | thrown a bag of parts and no description of what to build | or how to do it. | | To be honest that entire pypa doc should be like two | paragraphs long instead of 1000+ words. It should be | basically, "ok to package your python app just run | <official python tool to init a package>, that's it you're | done!". Every decision should be made for me, like it is | with npm, cargo, etc. I shouldn't have to think beyond | running one command. | | That's what python end users need. We don't need a million | tools and huge docs with seemingly no vision or goal. We | need to get shit done and the less time we faff about with | packaging and tooling the better. | Izkata wrote: | AFAIK in the python 2 era it was the de-facto standard (just | swap "python -m venv" with "virtualenv"). All these new tools | have just made it more complicated and it's not clear to me | what they gain, seems to me like they've simply succeeded in | convincing people it's complicated by obscuring what's | actually going on. | fbdab103 wrote: | A few weeks ago, I was attempting to help introduce someone | to Python. I felt embarrassed at trying to paper-over how | complicated and confusing the initial configuration is for a | newbie. No officially endorsed best-practices to which I | could point. Half a dozen tribes with their own competing | solutions and guidance. | | A definitive statement from Python.org as to The Way would go | so far. | samwillis wrote: | Ultimately it needs to be "Python.org" that endorses the tool, | not PyPA, no one in the scheme of things know who PyPA are and | if it's the "one true way". | | If you go to Python.org and follow through to the beginners | guide [0] this is what's suggested: | | > _There are several methods to install additional Python | packages:_ | | > _Packages can be installed via the standard Python distutils | mode (python setup.py install)._ | | > _Many packages can also be installed via the setuptools | extension or pip wrapper, seehttps://pip.pypa.io/._ | | That is so out of date and fundamentally confuses people coming | to Python for the first time. How is pip secondary, and no | mention of venv? | | The PyPA need to get buy in from Python Core to put one tool | front and centre first. It needs to be like Rust with Cargo, | literally the first thing you learn to use and core to all | beginners guides. | | That's not to diminish the work of PyPA, you are all amazing I | just want your work to be more obvious! | | 0: https://docs.python.org/3/using/mac.html#installing- | addition... | Godel_unicode wrote: | The future is here, it's just inconsistently distributed. | There's also the problem of python.org not wanting to pick | winners, i.e. not promoting activestate vs conda vs pypa. | | https://packaging.python.org/en/latest/tutorials/installing-. | .. | | https://packaging.python.org/en/latest/tutorials/packaging-p. | .. | agumonkey wrote: | where is the install .[dev] | | format/syntax defined ? I was trying to find what was possible | and how to make sense of it in setup.cfg tools | | I found one mention in the docs but no more. | baq wrote: | you may have done pip install | jupyter[notebook] | | this is the same thing, just for . (current directory) and | dev variant. | agumonkey wrote: | yeah but I'm missing data on how variant interacts with | various requirements defined in setup.cfg (testing | dependencies for instance) | woodruffw wrote: | Yep. The key difference is that the former is specified in | PEP 508, while `.` and its variants are a convenience | feature that pip (and maybe some other tools) provide. | woodruffw wrote: | It's a pip-ism; as far as I know, it's not defined in any | PEP. It should be in their documentation, however. | agumonkey wrote: | gonna dig deeper there then, thanks | nprescott wrote: | PEP-508[0] explains the grammar for "extras": | | > Optional components of a distribution may be specified | using the extras field: identifier_end = | letterOrDigit | (('-' | '_' | '.' )* letterOrDigit) | identifier = letterOrDigit identifier_end* name | = identifier extras_list = identifier (wsp* ',' wsp* | identifier)* extras = '[' wsp* extras_list? wsp* | ']' | | as well as explaining their behavior, albeit briefly: | | > Extras union in the dependencies they define with the | dependencies of the distribution they are attached to. | | The resolution on . is explained by the pip documentation[1]: | | > pip looks for packages in a number of places: on PyPI (if | not disabled via --no-index), in the local filesystem, and in | any additional repositories specified via --find-links or | --index-url. There is no ordering in the locations that are | searched. Rather they are all checked, and the "best" match | for the requirements (in terms of version number - see PEP | 440 for details) is selected. | | [0]: https://peps.python.org/pep-0508/#grammar | | [1]: https://pip.pypa.io/en/stable/cli/pip_install/#finding- | packa... | nezirus wrote: | Reading this is really depressing. I just want Cargo for Python. | Poetry it is for now, but it has quirks, and it is dog slow... | DangitBobby wrote: | I have a single, simple script (not a package!) that has | dependencies. Actually, I have a few of these, just sitting in | /usr/local/bin so I can execute them whenever. | | How should I be managing environments for these scripts? Do I | install dependencies in shared system python? Should I create a | shared venv? Where should I store it? Any tools out there that | make this decision for you and manage it? | | Just the fact that homebrew occasionally updates my installed | Pythons and breaks everything makes me reluctant to use Python as | a scripting language at all. It's pretty reliable when I have a | folder dedicated to a project (poetry is good for this) but I'm | pretty fed up with how brittle it all is. | DangitBobby wrote: | In an amazing coincidence, I just found another front-page post | exploring this same topic! For Python, it seems to suggest | using nix-shell. | | 1. https://dbohdan.com/scripts-with-dependencies | DangitBobby wrote: | My comment with an example of a single file script which can | specify its own dependencies: | | https://news.ycombinator.com/item?id=34393630 | saila wrote: | If you don't mind adding a pyproject.toml, you could use | pipx[1] to install these scripts. The directory structure would | look like this: <name>/ | pyproject.toml <name>.py | | The pyproject.toml would look like this (using poetry, but you | could use a different tool for this): | [tool.poetry] # NOTE: Set <name> to your project name | name = "<name>" description = "My Script" | version = "0.0.0" authors = ["Me <me@example.com>"] | [tool.poetry.dependencies] python = "^3.11" | requests = "^2.28.2" [tool.poetry.scripts] | # NOTE: Change <name> to match your package name in | [tool.poetry] <name> = "<name>:main" | [build-system] requires = ["poetry-core"] | build-backend = "poetry.core.masonry.api" | | Then you'd run `pipx install -e .` and the the executable | script will be installed in ~/.local/bin. | | [1] https://pypa.github.io/pipx/ | DangitBobby wrote: | Thank you for trying to provide a workable solution, it's | really not bad, but it has some downsides for me. pipx itself | is installed inside a python environment, so when brew breaks | my pythons, it breaks pipx as well. Anytime brew breaks my | pythons, I would need to do the install step again for every | script (or write a tool myself which does it). Not a total | deal breaker, but not really much better than my current | situation which pretty much just assumes any version of | `requests` or `fire` is acceptable. Because python itself is | constantly being updated to break the base python environment | on my machine, a workable solution would need to include the | fact that the base python environment might need to have | things installed. | noisy_boy wrote: | One option could be to have Python installed in a separate | location specifically for this purpose and to NOT include | it in PATH. Then it is "out-of-sight" of brew and such | packages and sort. You can even make the entire location | read-only once you are done with installation of Python + | pipx etc. | DangitBobby wrote: | That would definitely work. | fleekonpoint wrote: | I use a separate directory and venv for each script. To execute | the script, I use a shell script to call the venv's python | interpreter. This is also how I use python scripts with | cron/systemd. #!/bin/bash # | myscript.sh venv/bin/python3 myscript.py | | You could also skip the shell script and use aliases in your | .bashrc. | DangitBobby wrote: | I do something kind of like this, but all of my scripts break | when the underlying env is suddenly broken when e.g. brew | updates python without asking me and breaks all existing | environments. | | I'm sure I could come up with solutions that are very robust | for my particular machine, but I would like something that | allows me to share it as a gist and a teammate could just as | easily use it, or I can use it myself on another machine | without hassle. In other words, a solution contained within | the script iteself and maybe one or two binaries outside that | make it possible. | fleekonpoint wrote: | I see, it might be heavy handed but running them inside | Docker containers might provide you with the isolation | you're looking for. You could also build and share these | images with your teammates. | | I've actually started using a lot of different CLI tools | with Docker, especially when the tool isn't available for | my OS. | wpietri wrote: | I don't understand how there still isn't a good answer for | this. It seems like such an obvious need, and for years I've | heard go being promoted for solving this problem. I get why | Python didn't start out with an answer for this, but in an era | of 20 TB hard drives, I'm more than willing to burn space for | ease of install. | tempest_ wrote: | I've pretty much settled on poetry for most things at this point. | | It still has a ton of rough edges like error messages still | closer to a stack trace than something actionable and it's slow | as hell resolving but it does the job 90 percent of the time | without issue. | | Also running everything in docker now anyway which side steps | some other problems. | npage97 wrote: | For anyone curious, the reasoning for the slowness is briefly | described here: https://python-poetry.org/docs/faq/#why-is-the- | dependency-re... | odiroot wrote: | Poetry still doesn't seem to support PEP621, instead requiring | its custom, vendor-specific shape of pyproject.toml. | gen220 wrote: | Have they spoken about why they don't support it? Or plans to | support it in the future? | | It seems like the shortest path to a universal package | management tool for Python is to add this capability to | Poetry, rather than to build something new. | imglorp wrote: | That's where we are as well, but yes the problems you didn't | sidestep with poetry+docker are still there: the pypi | fecosystem out there does not stop quantum fluctuations just | because you want it to. If you pin too much you're not getting | security fixes and if you don't pin enough, you get bitten | every time a tertiary dep changes that you never asked for. Oh | yeah and there are now trojans upstream almost daily. | tempest_ wrote: | Yeah but that trade off is entirely separate. | | We trade security for speed(or "velocity" if you want to be | jargon about it). | | I just pin everything and go through my projects every couple | weeks and bump the deps (unless some really big CVE hits the | news). | gen220 wrote: | Does any FOSS package ecosystem have a good solution to this | particular set of problems? | | I know Go has historically done something interesting with | selecting the "minimum viable version number" for each | dependency, but that's the only relevant idea that comes to | mind. | | With PyPi, at least it's relatively trivial to self-host a | pypi instance and self-manage dependency updates. | | In the Python ecosystem (vs e.g. Node), at least the total | set of first+second-order dependencies for most normal | projects is quite small (e.g. medium double digits to low | triple digits). It doesn't feel too painful to manage that | magnitude of upgrades on a monthly or quarterly basis. | samwillis wrote: | This post is prompted by the survey of Python users, their | feedback, and a current thread [0] on the Python forms discussing | a way forward. I read the thread the other day, it's long, and | there are a lot of opinions. | | Towards the end of this post there is an interesting observation: | | > _Discourse, the platform that the discussion was held on, shows | the number of times a link was clicked. Granted, this count might | not be always accurate, but if we assume it is, the link to the | results summary was clicked only 14 times (as of 2023-01-14 21:20 | UTC). The discussion has 28 participants and 2.2k views. If we | believe the link click counter, half of the discussion | participants did not even bother reading what the people think._ | | Along with that, my concern is that there are too my cooks in the | kitchen. A packaging system is never going to cater for more than | 90% of use cases, but there will likely be a higher than average | representation from people who would sit in the 10%. There is a | danger of them never being able to agree on a solution that | solves all problems, and then never launch anything. | | It would be far better to get _something_ out, have a stake in | the ground, and build from there. It also desperately needs to be | "Core Python", my understanding is that the PyPA (Python Package | Authority) is somewhat disconnected from the core Python | development. | | Ultimately they need one system that is front and centre, that is | the "officially endorsed" tool, and very clear messaging on that. | | 0: https://discuss.python.org/t/python-packaging-strategy- | discu... | noisy_boy wrote: | > Ultimately they need one system that is front and centre, | that is the "officially endorsed" tool, and very clear | messaging on that. | | I think this is important; otherwise there is a risk behind | switching to a new packaging tool and then it being subject to | neglect/lack of resources - that makes people averse to | switching to it. That is why virtualenv/pip is the lowest | common denominator - everyone knows that worst case, those will | always continue to work. The "official" tool needs to inspire | that sort of confidence. | nmstoker wrote: | Yes, there was some questionable comms around pipenv being | "officially recommdnded" which upon closer inspection seemed | to have come from the people who wrote it and not really been | that official so far as I could see! That seems to have been | walked back after a while but not before it gained traction | and randoms bring up that it's official even now. | carapace wrote: | I think you're right. At risk of making a "lowbrow dismissal" | the very length of TFA is a clear symptom of the problem: | _Design-by-committee_ (The PyPA (Python Package Authority) | reminds me of the movie _Brazil_. Don 't get me started.) | | - - - - | | Someone should do for packaging what _pathlib_ did for file I | /O: make a Pythonic model/API for it. Then deployment becomes | simple, scriptable, testable, repeatable, etc... | woodruffw wrote: | This might be a fun thought to entertain, but the PyPA | doesn't really form design committees (at least, I haven't | been on one). You can see exactly how Python packaging | standards are made: they're done with PEPs[1], exactly the | same as with every other Python standardization effort. | | Indeed, most packaging PEPs start out exactly the way you've | laid out: a tool or service writes a Pythonic API or model, | and it gets standardized so that other tools can rely on it. | TFA's problems (which are real ones!) stem mostly from the | error before there were serious standardization efforts among | Python packaging tools. | | [1]: https://peps.python.org/topic/packaging/ | carapace wrote: | > _Don 't get me started._ | marsten wrote: | > there will likely be a higher than average representation | from people who would sit in the 10% | | And also an under-representation of "average users". | | Python the language has always benefitted from its relative | simplicity, which I attribute to people like GVR saying "no" to | specialized features that accrue on languages like barnacles on | a ship (looking at you C++). | | With newer languages we see core design teams being much more | opinionated about tooling for build and dependendency/packaging | management. This is no doubt in response to the dumpster fires | of C++ and Python, where "the ecosystem will sort itself out" | clearly hasn't worked. | mkoubaa wrote: | I always like to say that's barring divine inspiration, it's | impossible to make the right choice. It's far more possible to | make a choice and then work hard to make it right | forkerenok wrote: | Thanks, this is an interesting nugget. Did you intend to append | a link reference for [0]? | samwillis wrote: | Yes, edited. Thanks. | benreesman wrote: | Trying to build Python under Nix (i.e. solid, not "close enough) | is an education in how fucked up the Python packaging ecosystem | is. | | Which is a shame because Python is an amazing scripting language, | the de facto numerical computing standard, and probably a better | bash for most bash use cases. | synergy20 wrote: | So we should all use PDM then as it's the best so far among all | others? I read it somewhere once in the past but never used it. I | just use `venv + pip` all the time so far, worked well for my | case though. | jasonhansel wrote: | Over time, I've grown to appreciate "pip-tools." Since it's a | dead-simple extension of pip, I wish it could be upstreamed into | pip itself; that seems like the most straightforward way of | fixing a number of Python's packaging issues. | vlovich123 wrote: | Yup. I like to make it so that each executable has a symlink to | a shell script. | | The shell script checks if there's a virtual environment set up | with the packages in the requirements.txt installed (it takes a | snapshot of the file because virtualenv doesn't have a DB to | query cheaply). Once the environment is set up, it dispatches | to running from the virtualenv. | | That way when you update a requirements.in file it recompiles | it (if the txt is out of date) and installs any new packages, | removes packages that shouldn't be there anymore and updates | ones whose version changed (if there's any changes found). It | also lets you trivially run tools with disparate | requirements.in without conflicts because each is siloed behind | its own virtualenv. | | This makes it a trivial experience to use these tools in a | shared repo because there's no worrying about packages / | needing to remember to run some command before the right | environment is set up. You just modify your code and run it | like a regular command-line tool and packages automatically get | deployed. It's also amenable to offline snapshotting / | distribution. In fact, I used this to distribute support | tooling for factory lines of the Pixel Buds and it worked | extremely well. | orf wrote: | You've described a worse, homegrown version of poetry. | delijati wrote: | I work on mutlirepos and i really dislike gits subtree, subrepo | i use https://pypi.org/project/zc.buildout/. Yes i know i can | do [1]. But editing on multirepos at the same time i can only | do with zc.buildout [2] Still not perfect but it does the job. | | [1] $ cat req.txt requests | git+ssh://git@gitlab.com/foo/bar/amber.git@0.4.0 | git+ssh://git@gitlab.com/foo/bar/rebam.git@0.4.0 | | [2] $ cat buildout.cfg [buildout] | extends = versions.cfg extensions = mr.developer | auto-checkout = \* develop = . show-picked- | versions = true update-versions-file = versions.cfg | sources-dir = git-sources parts = py | eggs = amber rebam hammer | [sources] amber = git | git@gitlab.com/foo/bar/amber.git@0.4.0 rebma = git | git@gitlab.com/foo/bar/rebma.git@0.4.0 [py] | recipe = zc.recipe.egg eggs = | ${buildout:eggs} interpreter = py-backend | dependent-scripts = true | pdw wrote: | Yes. It usually gets glossed over, but if you're building a | Python application it's all you need. | TigerTeamX wrote: | I must admit I just gave up on all these tools. Instead I just do | pip install -r requirements.txt -t .lib | | and I have import sys import os | sys.path.append(f"{os.getcwd()}/.lib") | | in the top of my script. Some will tell me this is silly, but it | just works. Rememer to at .lib to your .gitignore. Else you'll | have lot of fun. | TigerTeamX wrote: | This is similar to how node is doing. I just basically copied | that idea. | hkgjjgjfjfjfjf wrote: | [dead] | reducesuffering wrote: | https://chriswarrick.com/blog/2023/01/15/how-to-improve-pyth... | | Is quite damning on how much of a better experience Node/JS/TS | NPM is than Python's clusterfuck. Working with any other JS/TS | open source is easy to get running. Even if you use Poetry in | Python, you will run into everyone else using pip-tools, pipenv, | pdm, conda, etc. | baggiponte wrote: | been using pdm since at least one year and have no regrets: it's | the go tool and we should flock to it! ___________________________________________________________________ (page generated 2023-01-15 23:00 UTC)