Live data from Hacker News

A year of uv: pros, cons, and should you migrate

bitecode.dev

251–260 of 401 posts

Re: A year of uv: pros, cons, and should you migrate

#251
post #43

A very well written article! I admire the analysis done by the author regarding the difficulties of Python packaging. With the advent of uv, I'm finally feeling like Python packaging is solved. As mentioned in the article, being able to have inline dependencies in a single-file Python script and running it naturally is just beautiful. #!/usr/bin/env -S uv run # /// script # dependencies = ['requests', 'beautifulsoup4…

Any flow that does not state checksums/hashsums is not ready for production and all but beautiful. But I haven't used uv yet, so maybe it is possible to specify the dependencies with hashsums in the same file too? Actually the order of import statement is one of the things, that Python does better than JS. It makes completions much less costly to calculate when you type the code. An IDE or other tool only has to chec…

>Any flow that does not state checksums/hashsums is not ready for production

It's not designed nor intended for such. There are tons of Python users out there who have no concept of what you would call "production"; they wrote something that requires NumPy to be installed and they want to communicate this as cleanly and simply (and machine-readably) as possible, so that they can give a single Python file to associates and have them be able to use it in an appropriate environment. It's explicitly designed for users who are not planning to package the code properly in a wheel and put it up on PyPI (or a private index) or anything like that.

>and all but beautiful

De gustibus non est disputandum. The point is to have something simple, human-writable and machine-readable, for those to whom it applies. If you need to make a wheel, make one. If you need a proper lock file, use one. Standardization for lock files is finally on the horizon in the ecosystem (https://peps.python.org/pep-0751/).

>Actually the order of import statement is one of the things, that Python does better than JS.

Import statements are effectively unrelated to package management. Each installed package ("distribution package") may validly define zero or more top-level names (of "import packages") which don't necessarily bear any relationship to each other, and the `import` syntax can validly import one or more sub-packages and/or attributes of a package or module (a false distinction, anyway; packages are modules), and rename them.

>An IDE or other tool only has to check one module or package for its contents

The `import` syntax serves these tools by telling them about names defined in installed code, yes. The PEP 723 syntax is completely unrelated: it tells different tools (package managers, environment managers and package installers) about names used for installing code.

>Why not have smaller venvs for separate projects? It is really not that hard to do

It isn't, but it introduces book-keeping (Which venv am I supposed to use for this project? Where is it? Did I put the right things in it already? Should I perhaps remove some stuff from it that I'm no longer using? What will other people need in a venv after I share my code with them?) that some people would prefer to delegate to other tooling.

Historically, creating venvs has been really slow. People have noticed that `uv` solves this problem, and come up with a variety of explanations, most of which are missing the mark. The biggest problem, at least on Linux, is the default expectation of bootstrapping Pip into the new venv; of course uv doesn't do this by default, because it's already there to install packages for you. (This workflow is equally possible with modern versions of Pip, but you have to know some tricks; I describe some of this in https://zahlman.github.io/posts/2025/01/07/python-packaging-... . And it doesn't solve other problems with Pip, of course.) Anyway, the point is that people will make single "sandbox" venvs because it's faster and easier to think about - until the first actual conflict occurs, or the first attempt to package a project and accurately convey its dependencies.

> Avoiding deps for small scripts is a good thing! If possible.

I'd like to agree, but that just isn't going to accommodate the entire existing communities of people writing random 100-line analysis scripts with Pandas.

>One may complain in many ways about how NPM works, but it has had automatic lock file for aaages.

Cool, but the issues with Python's packaging system are really not comparable to those of other modern languages. NPM isn't really retrofitted to JavaScript; it's retrofitted to the Node.JS environment, which existed for only months before NPM was introduced. Pip has to support all Python users, and Python is about 18 years older than Pip (19 years older than NPM). NPM was able to do this because Node was a new project that was being specifically designed to enable JavaScript development in a new environment (i.e., places that aren't the user's browser sandbox). By contrast, every time any incremental improvement has been introduced for Python packaging, there have been massive backwards-compatibility concerns. PyPI didn't stop accepting "egg" uploads until August 1 2023 (https://blog.pypi.org/posts/2023-06-26-deprecate-egg-uploads...), for example.

But more importantly, npm doesn't have to worry about extensions to JavaScript code written in arbitrary other languages (for Python, C is common, but by no means exclusive; NumPy is heavily dependent on Fortran, for example) which are expected to be compiled on the user's machine (through a process automatically orchestrated by the installer) with users complaining to anyone they can get to listen (with no attempt at debugging, nor at understanding whose fault the failure was this time) when it doesn't work.

There are many things wrong with the process, and I'm happy to criticize them (and explain them at length). But "everyone else can get this right" is usually a very short-sighted line of argument, even if it's true.

Re: A year of uv: pros, cons, and should you migrate

#252
post #43

A very well written article! I admire the analysis done by the author regarding the difficulties of Python packaging. With the advent of uv, I'm finally feeling like Python packaging is solved. As mentioned in the article, being able to have inline dependencies in a single-file Python script and running it naturally is just beautiful. #!/usr/bin/env -S uv run # /// script # dependencies = ['requests', 'beautifulsoup4…

This is a nice feature, but I've not found it to be useful, because my IDE wont recognize these dependencies. Or is it a skill issue?

What exactly do you imagine that such "recognition" would entail? Are you expecting the IDE to provide its own package manager, for example?

Re: A year of uv: pros, cons, and should you migrate

#253

Has someone migrated from poetry to uv? Any benefits?

In addition to all the benefits others have mentioned, biggest benefit for me was that with uv you can easily bring your own build system (scikit-build-core in my case). Poetry comes with its own build system that didn't work for my needs and working around that was a massive pain and quite fragile. With uv I can use the build system that works best for me. On the whole uv is less opinionated than poetry. By default it will do sensible things, but if that thing doesn't work in your particular weird case, it is much easier to make uv work for you than poetry. Poetry gets very angry if you try to hold it wrong.

Re: A year of uv: pros, cons, and should you migrate

#254
post #12

Well, big fan of uv. But... the 86GB python dependency download cache on my primary SSD, most of which can be attributed to the 50 different versions of torch, is testament to the fact that even uv cannot salvage the mess that is pip. Never felt this much rage at the state of a language/build system in the 25 years that I have been programming. And I had to deal with Scala's SBT ("Simple Build Tool") in another life.

Try building uv itself. Cargo used something like 40GiB of disk space somehow.

I am only criticizing python because I am actively using it.

The node ecosystem and the rust one seem to have their own issues. I have zero interest in either of them so I haven't looked into them in detail.

However, I have to deal with node on occasion because a lot of JS/CSS tooling is written using it. It has a HUGE transitive dependency problem.

Re: A year of uv: pros, cons, and should you migrate

#255
post #43

A very well written article! I admire the analysis done by the author regarding the difficulties of Python packaging. With the advent of uv, I'm finally feeling like Python packaging is solved. As mentioned in the article, being able to have inline dependencies in a single-file Python script and running it naturally is just beautiful. #!/usr/bin/env -S uv run # /// script # dependencies = ['requests', 'beautifulsoup4…

You know what we need? In both python and JS, and every other scripting language, we should be able to import packages from a url, but with a sha384 integrity check like exists in HTML. Not sure why they didn't adopt this into JS or Deno. Otherwise installing random scripts is a security risk

The code that you obtain for a Python "package" does not have any inherent mapping to a "package" that you import in the code. The name overload is recognized as unfortunate; the documentation writing community has been promoting the terms "distribution package" and "import package" as a result.

https://packaging.python.org/en/latest/discussions/distribut...

https://zahlman.github.io/posts/2024/12/24/python-packaging-...

While you could of course put an actual Python code file at a URL, that wouldn't solve the problem for anything involving compiled extensions in C, Fortran etc. You can't feasibly support NumPy this way, for example.

That said, there are sufficient hooks in Numpy's `import` machinery that you can make `import foo` programmatically compute a URL (assuming that the name `foo` is enough information to determine the URL), download the code and create and import the necessary `module` object; and you can add this with appropriate priority to the standard set of strategies Python uses for importing modules. A full description of this process is out of scope for a HN comment, but relevant documentation:

https://docs.python.org/3/library/importlib.html

https://docs.python.org/3/library/sys.html#sys.meta_path

Re: A year of uv: pros, cons, and should you migrate

#256

Earlier quoted context omitted.

One other key part of this is freezing a timestamp with your dependency list, because Python packages are absolutely terrible at maintaining compatibility a year or three or five later as PyPI populates with newer and newer versions. The special toml incantation is [tool.uv] exclude-newer: # /// script # dependencies = [ # "requests", # ] # [tool.uv] # exclude-newer = "2023-10-16T00:00:00Z" # /// https://docs.astral.…

Why didn't you create a lock file with the versions and of course hashsums in it? No version hunting needed.

Because the aim is to have a single file, fairly short, script. Even if we glued the lock file in somehow, it would be huge!

I prefer this myself, as almost all lock files are in practice “the version of packages at this time and date”, so why not be explicit about that?

Re: A year of uv: pros, cons, and should you migrate

#257
post #43

A very well written article! I admire the analysis done by the author regarding the difficulties of Python packaging. With the advent of uv, I'm finally feeling like Python packaging is solved. As mentioned in the article, being able to have inline dependencies in a single-file Python script and running it naturally is just beautiful. #!/usr/bin/env -S uv run # /// script # dependencies = ['requests', 'beautifulsoup4…

One other key part of this is freezing a timestamp with your dependency list, because Python packages are absolutely terrible at maintaining compatibility a year or three or five later as PyPI populates with newer and newer versions. The special toml incantation is [tool.uv] exclude-newer: # /// script # dependencies = [ # "requests", # ] # [tool.uv] # exclude-newer = "2023-10-16T00:00:00Z" # /// https://docs.astral.…

This is the feature I would most like added to rust, if you don’t save a lock file it is horrible trying to get back to the same versions of packages.

Re: A year of uv: pros, cons, and should you migrate

#258
Can anyone explain to a non-python developer why python infrastructure is so much broken around the version management?

It looks to me that every new minor python release is a separate additional install because realistically you cannot replace python 3.11 with python 3.12 and expect things to work. How did they put themselves in such a mess?

Re: A year of uv: pros, cons, and should you migrate

#259

Like so many other articles that make some offhand remarks about conda, this article raves about a bunch of "new" features that conda has had for years. > Being independent from Python bootstrapping Yep, conda. > Being capable of installing and running Python in one unified congruent way across all situations and platforms. Yep, conda. > Having a very strong dependency resolver. Yep, conda (or mamba). The main thing…

Good to see you again.

>Like so many other articles that make some offhand remarks about conda, this article raves about a bunch of "new" features that conda has had for years.

Agreed. (I'm also tired of seeing advances like PEP 723 attributed to uv, or uv's benefits being attributed to it being written in Rust, or at least to it not being written in Python, in cases where that doesn't really hold up to scrutiny.)

> The pro and con of tools like uv is that they layer over the base-level tools like pip. The pro of that is that they interoperate well with pip.

It's a pretty big pro ;) But I would say it's at least as much about "layering over the base-level tools" like venv.

> The con is that they inherit the limitations of that packaging model (notably the inability to distribute non-Python dependencies separately).

I still haven't found anything that requires packages to contain any Python code (aside from any build system configuration). In principle you can make a wheel today that just dumps a platform-appropriate shared library file for, e.g. OpenBLAS into the user's `site-packages`; and others could make wheels declaring yours as a dependency. The only reason they wouldn't connect up - that I can think of, anyway - is because their own Python wrappers currently don't hard-code the right relative path, and current build systems wouldn't make it easy to fix that. (Although, I guess SWIG-style wrappers would have to somehow link against the installed dependency at their own install time, and this would be a problem when using build isolation.)

Re: A year of uv: pros, cons, and should you migrate

#260

Has anyone built pipy packages with `uv`? Does doing so affect the end-user at all?

Works fine. But for people on Github for now I recommend using uv only for building distributions and using the official PyPA GitHub action for publishing them to PyPI. This way you can take advantage of attestation, something not yet supported by uv.
Post reply on HN