[HN Gopher] How uv got so fast
___________________________________________________________________
How uv got so fast
Author : zdw
Score : 1191 points
Date : 2025-12-26 17:13 UTC (1 days ago)
(HTM) web link (nesbitt.io)
(TXT) w3m dump (nesbitt.io)
| yjftsjthsd-h wrote:
| > No bytecode compilation by default. pip compiles .py files to
| .pyc during installation. uv skips this step, shaving time off
| every install. You can opt in if you want it.
|
| Are we losing out on performance of the actual installed thing,
| then? (I'm not 100% clear on .pyc files TBH; I'm _guessing_ they
| speed up start time?)
| woodruffw wrote:
| No, because Python itself will generate bytecode for packages
| once you actually import them. uv just defers that to first-
| import time, but the cost is amortized in any setting where
| imports are performed over multiple executions.
| yjftsjthsd-h wrote:
| That sounds like yes? Instead of doing it once at install
| time, it's done once at first use. It's only once so it's not
| _persistently_ slower, but that is a perf hit.
|
| My first cynical instinct is to say that this is uv making
| itself look better by deferring the costs to the application,
| but it's probably a good trade-off if any significant
| percentage of the files being compiled might not be used ever
| so the overall cost is lower if you defer to run time.
| woodruffw wrote:
| > It's only once so it's not persistently slower, but that
| is a perf hit.
|
| Sure, but you pay that hit either way. Real-world
| performance is always usage based: the assumption that uv
| makes is that people run (i.e. import) packages more often
| than they install them, so amortizing at the point of the
| import machinery is better for the mean user.
|
| (This assumption is not universal, naturally!)
| dddgghhbbfblk wrote:
| Ummm, your comment is backwards, right?
| woodruffw wrote:
| Which part? The assumption is that when you `$TOOL
| install $PACKAGE`, you run (i.e. import) `$PACKAGE` more
| than you re-install it. So there's no point in slowing
| down (relatively less common) installation events when
| you can pay the cost once on import.
|
| (The key part being that 'less common' doesn't mean a
| non-trivial amount of time.)
| dddgghhbbfblk wrote:
| Why would you want to slow down the more common thing
| instead of the less common thing? I'm not following that
| at all. That's why I asked if that's backwards.
| woodruffw wrote:
| Because you only slow down the more common thing once,
| and the less common thing is slower in absolute terms.
| lillecarl wrote:
| uv optimizes for the common usecase: You will install
| more packages than you will import new packages.
| beacon294 wrote:
| Probably for any case where an actual human is doing it. On
| an image you obviously want to do it at bake time, so I
| feel default off with a flag would have been a better
| design decision for pip.
|
| I just read the thread and use Python, I can't comment on
| the % speedup attributed to uv that comes from this
| optimization.
| Epa095 wrote:
| Images are a good example where doing it at install-time
| is probably the best yeah, since every run of the image
| starts 'fresh', losing the compilation which happened
| last time the image got started.
|
| If it was a optional toggle it would probably become best
| practice to activate compilation in dockerfiles.
| zahlman wrote:
| > On an image you obviously want to do it at bake time
|
| It seems like tons of people are creating container
| images with an installer tool and having it do a bunch of
| installations, rather than creating the image with the
| relevant Python packages already in place. Hard to
| understand why.
|
| For that matter, a pre-baked Python install could do much
| more interesting things to improve import times than just
| leaving a forest of `.pyc` files in `__pycache__` folders
| all over the place.
| saidnooneever wrote:
| you are right. it depends on how often this first start is,
| if its bad or not..most usecases id guess (total guess,
| have limited exp with python projects professionally) its
| not an issue.
| tedivm wrote:
| You can change it to compile the bytecode on install with a
| simple environment variable (which you should do when
| building docker containers if you want to sacrifice some
| disk space to decrease initial startup time for your app).
| VorpalWay wrote:
| I think they are making the bet that most modules won't be
| imported. For example if I install scipy, numpy, Pillow or
| such: what are the chances that I use a subset of the
| modules vs literally all of them?
|
| I would bet on a subset for pretty much any non-trivial
| package (i.e. larger than one or two user facing modules).
| And for those trivial packages? Well they are usually
| small, so the cost is small as well. I'm sure there are
| exceptions: maybe a single gargantuan module thst consists
| of autogenerated FFI bindings for some C library or such,
| but that is likely the minority.
| zmgsabst wrote:
| That's actually a negative:
|
| My Docker build generating the byte code saves it to the
| image, sharing the cost at build time across all image
| deployments -- whereas, building at first execution means
| that each deployed image instance has to generate its own
| bytecode!
|
| That's a _massive_ amplification, on the order of 10-100x.
|
| "Well just tell it to generate bytecode!"
|
| Sure -- but when is the default supposed to be better?
|
| Because this sounds like a massive footgun for a system where
| requests >> deploys >> builds. That is, every service I've
| written in Python for the last decade.
| salviati wrote:
| Historically the practice of producing pyc files on install
| started with system wide installed packages, I believe, when
| the user running the program might lack privileges to write
| them. If the installer can write the .oy files it can also
| write the .pyc, while the user running them might not in that
| location.
| plorkyeran wrote:
| If you have a dependency graph large enough for this to be
| relevant, it almost certainly includes a large number of files
| which are never actually imported. At worst the hit to startup
| time will be equal to the install time saved, and in most cases
| it'll be a lot smaller.
| zahlman wrote:
| > a large number of files which are never actually imported
|
| Unfortunately, it typically doesn't work out as well as you
| might expect, especially given the expectation of putting
| `import` statements at the top of the file.
| hauntsaninja wrote:
| Yes, uv skipping this step is a one time significant hit to
| start up time. E.g. if you're building a Dockerfile I'd
| recommend setting `--compile-bytecode` / `UV_COMPILE_BYTECODE`
| thundergolfer wrote:
| This optimization hits serverless Python the worst. At Modal we
| ensure users of uv are setting UV_COMPILE_BYTECODE to avoid the
| cold start penalty. For large projects .pyc compilation can
| take hundreds of milliseconds.
| zahlman wrote:
| > I'm not 100% clear on .pyc files TBH; I'm guessing they speed
| up start time?
|
| They do.
|
| > Are we losing out on performance of the actual installed
| thing, then?
|
| When you consciously precompile Python source files, you can
| parallelize that process. When you `import` from a `.py` file,
| you only get that benefit if you somehow coincidentally were
| already set up for `multiprocessing` and happened to have your
| workers trying to `import` different files at the same time.
| blintz wrote:
| > PEP 658 went live on PyPI in May 2023. uv launched in February
| 2024. The timing isn't coincidental. uv could be fast because the
| ecosystem finally had the infrastructure to support it. A tool
| like uv couldn't have shipped in 2020. The standards weren't
| there yet.
|
| How/why did the package maintainers start using all these
| improvements? Some of them sound like a bunch of work, and
| getting a package ecosystem to move is hard. Was there motivation
| to speed up installs across the ecosystem? If setup.py was
| working okay for folks, what incentivized them to start using
| pyproject.toml?
| yjftsjthsd-h wrote:
| Because static declaration was clearly safer and more
| performant? My question is why pip isn't fully taking advantage
| eesmith wrote:
| Because pip contains decades of built-up code and lacks the
| people willing to work on updating it.
| zahlman wrote:
| > If setup.py was working okay for folks, what incentivized
| them to start using pyproject.toml?
|
| It wasn't working okay for many people, and many others haven't
| started using pyproject.toml.
|
| For what I consider the most egregious example: Requests is one
| of the most popular libraries, under the PSF's official
| umbrella, which uses only Python code and thus doesn't even
| need to be "built" in a meaningful sense. It has a
| pyproject.toml file as of the last release. But that file _isn
| 't specifying the build setup_ following PEP 517/518/621
| standards. That's supposed to appear in the next minor release,
| but they've only done patch releases this year and the relevant
| code is not at the head of the repo, _even though it already
| caused problems for them this year_. It 's been more than a
| year and a half since the last minor release.
| zahlman wrote:
| I should have mentioned one of the main reasons setup.py
| turns out not okay for people (aside from the general
| unpleasantness of running code to determine what should be,
| and mostly is, static metadata): in the legacy approach,
| Setuptools has to get `import`ed from the `setup.py` code
| before it can run, but running that code is the way to find
| out the dependencies. Including build-time dependencies.
| Specifically Setuptools itself. Good luck if the user's
| installed version is incompatible with what you've written.
| pnt12 wrote:
| That's really unfortunate, and it sounds like a quick thing
| to fix. Is there a pull request with that?
| zahlman wrote:
| There's been a branch for it
| (https://github.com/psf/requests/tree/hatchling) for a
| little while apparently; I guess they won't merge it until
| absolutely necessary for the 2.33 release. But that is
| still just over a year after I offered
| (https://github.com/psf/requests/issues/6775).
|
| ... Ah, I got confused for a bit. When I first noticed the
| `pyproject.toml` deficiency, it was because Requests was
| affected by the major Setuptools 72 backwards
| incompatibility. Then this year they were hit again by the
| major Setuptools _78_ backwards incompatibility (which the
| Setuptools team consciously ignored in testing because
| Requests already publishes their own wheel, so this only
| affected the build-from-source purists like distro
| maintainers). See also my writeup
| https://lwn.net/Articles/1020576/ .
| nxpnsv wrote:
| Hmm... poetry got me into using pyproject.toml, and with that
| migrating to uv was surprisingly easy.
| woodruffw wrote:
| I think this post does a really good job of covering how multi-
| pronged performance is: it certainly doesn't hurt uv to be
| written in Rust, but it benefits _immensely_ from a decade of
| thoughtful standardization efforts in Python that lifted the
| ecosystem away from needing `setup.py` on the hot path for most
| packages.
| yjftsjthsd-h wrote:
| I think a lot of rust rewrites have this benefit; if you start
| with hindsight you can do better more easily. Of course, rust
| is also _often_ beneficial for its own sake, so it 's a one-two
| punch:)
| woodruffw wrote:
| Completely agreed!
| pxc wrote:
| Succinctly, perhaps with some loss of detail:
|
| "Rewrite" is important as "Rust".
| pixelpoet wrote:
| as important as
| pxc wrote:
| whoops. That's right
| s_ting765 wrote:
| Rust rewrites are known for breaking (compatibility with)
| working software. That's all there is to them.
| pxc wrote:
| In Python's case, as the article describes quite clearly,
| the issue is that the design of "working software"
| (particularly setup.py) was bad to the point of insane (in
| much the same way as the NPM characteristics that enabled
| the recent Shai Hulud supply chain attacks, but even
| worse). At some point, compatibility with insanity has got
| to go.
|
| Helpfully, though, uv retains compatibility with newer (but
| still well-established) standards in the Python community
| that don't share this insanity!
| s_ting765 wrote:
| My gripe is with Rust rewrites. Not uv. Though I very
| much think uv is overhyped.
| eduction wrote:
| Actually uv retains compatibility with the setup.py
| "insanity," according to the article:
|
| > uv parses TOML and wheel metadata natively, only
| spawning Python when it hits a setup.py-only package that
| has no other option
|
| The article implies that pip also prefers toml and wheel
| metadata, but has to shell out to parse those, unlike uv.
| pxc wrote:
| Ugh. Thank you for the correction. :(
| eduction wrote:
| I mean, you're on the right track in that they did cut
| out other insanity. But unclear how much of the speed up
| is necessarily tied to breaking backward compat (are
| there a lot of ".egg" files in the wild?)
| zahlman wrote:
| > (are there a lot of ".egg" files in the wild?)
|
| Not as far as I can tell, except perhaps in extended-
| support legacy environments (for example, ActiveState is
| still maintaining a Python 2.x distribution).
| Lammy wrote:
| I would say the downside of them is that they're known for
| replacing GPL software with MIT software
| Levitating wrote:
| > I think a lot of rust rewrites have this benefit
|
| I think Rust itself has this benefit
| glaslong wrote:
| Someone once told me a benefit of staffing a project for
| Haskell was it made it easy to select for the types of
| programmers that went out of their way to become experts in
| Haskell.
|
| Tapping the Rust community is a decent reason to do a project
| in Rust.
| steve_adams_86 wrote:
| I'm my experience this is definitely where rust shined. The
| language wasn't really what made the project succeed so much
| as having relatively curious, meticulous, detail-oriented
| people on hand who were interested in solving hard problems.
|
| Sometimes I thought our teams would be a terrible fit for
| more cookie-cutter applications where rapid development and
| deployment was the primary objective. We got into the weeds
| all the time (sometimes because of rust itself), but it
| happened to be important to do so.
|
| Had we built those projects with JavaScript or Python I
| suspect the outcomes would have been worse for reasons apart
| from the language choice.
| zahlman wrote:
| > having relatively curious, meticulous, detail-oriented
| people on hand who were interested in solving hard
| problems.... Had we built those projects with JavaScript or
| Python I suspect the outcomes would have been worse for
| reasons apart from the language choice.
|
| I genuinely can't understand why you suppose that has to do
| with the implementation language at all.
| KPGv2 wrote:
| > I genuinely can't understand why you suppose that has
| to do with the implementation language at all.
|
| Languages that attract novice programmers (JS is an
| obvious one; PHP was one 20 years ago) have a higher
| noise to signal ratio than one that attracts intermediate
| and above programmers.
|
| If you grabbed an average Assembly programmer today, and
| an average JavaScript programmer today, who do you think
| is more careful about programming? The one who needs to
| learn arcane shit to do basic things and then has to
| compile it in order to test it out, or the one who can
| open up Chrome's console and console.log("i love
| boobies")
|
| How many embedded systems programmers suck vs full stack
| devs? I'm not saying full stack devs are inferior. I'm
| saying that more inferior coders are attracted to the
| latter because the barriers to entry are SO much easier
| to bypass.
| zahlman wrote:
| Sure, but that kind of incompetence is already filtered
| out (in the https://www.lesswrong.com/w/screening-off-
| evidence sense) by _the task_ of creating a package
| installer.
| IgorPartola wrote:
| You would think so, yet here I am sitting with a
| node_modules full of crud placed there by npm, waiting
| for the next supply chain attack.
| zahlman wrote:
| That argument is FUD. The people who created the NPM
| package manager are not the people who wrote your
| dependencies. Further, supply chain attacks occur for
| reasons that are entirely outside NPM's control.
| Fundamentally they're a matter of trust in the ecosystem
| -- in the very idea of installing the packages in the
| first place.
| firesteelrain wrote:
| Lack of stronger trust controls are part of the larger
| issue with npm. Pip, Maven and Go are not immune either
| but they do things structurally better to shift the
| problem.
|
| Go: Enforces global, append-only integrity via a checksum
| database and version immutability; once a module version
| exists, its contents cannot be silently altered without
| detection, shifting attacks away from artifact
| substitution toward "publish a malicious new version" or
| bypass the proxy/sumdb.
|
| Maven: Requires structured namespace ownership and signed
| artifacts, making identity more explicit at publish time;
| this raises the bar for casual impersonation but still
| fundamentally trusts that the key holder and build
| pipeline were not compromised.
| Mawr wrote:
| For Go, there are more impactful features: minimal
| version selection and the culture of fewer, but larger
| dependencies.
|
| Your average Go project likely has 10x fewer deps than a
| JS project. Those deps will not get auto-updated to their
| latest versions either. Much lower attack surface area.
| nl wrote:
| I don't see how that follows.
|
| uv doesn't exactly stop python package supply chain
| attacks...
| tacticus wrote:
| npm isn't the issue there it's the ts\js community and
| their desire to use a library for everything. in
| communities that do not consider dependencies to be a
| risk you will find this showing up in time.
|
| The node supply chain attacks are also not unique to node
| community. you see them happening on crates.io and many
| other places. In fact the build time scripts that cause
| issues on node modules are probably worse off with the
| flexibility of crate build scripts and that they're going
| to be harder to work around than in npm.
| LtWorf wrote:
| I don't think cargo is much better in that respect. It's
| what happens when instead of a decent standard library
| and a few well established frameworks you decide that
| every single little thing must be a separate project.
| tikhonj wrote:
| Different programming languages come with different
| _schools of thought_ about programming and different
| _communities of practice_ around programming.
|
| If you take a group of people who are squarely in the
| enterprise Java school of thought and have them write
| Rust, the language won't make _much_ of a difference.
| They will eventually be _influenced_ by the broader Rust
| community and the Rust philosophy towards programming,
| but, unless they 're already interested in changed
| approaches, this will be a small, gradual difference. So
| you'll end up with Enterprise Java(tm) code, just in
| Rust.
|
| But if you hire _from_ the Rust community, you will get
| people who have a fundamentally different set of
| practices and expectations around programming. They will
| not only have a stronger grasp of Rust and Rust idioms
| but will also have explicit knowledge based on Rust (eg
| Rust-flavored design patterns and programming techniques)
| and, crucially, _tacit_ knowledge based on Rust (Rust-
| flavored ways of programming that don 't break down into
| easy-to-explain rules). And, roughly speaking, the same
| is going to be true for whatever other language you
| substitute for "Rust".
|
| (I say _roughly_ because there doesn 't have to be a 1:1
| relationship between programming languages, schools of
| thought and communities of practice. A single language
| can have totally different communities--just compare web
| Python vs data scientist Python--and some
| communities/schools can span multiple languages. But, as
| an over-simplified model, seeing a language _as_ a
| community is not the worst starting point.)
| LtWorf wrote:
| Since currently 0% of developers started with rust, it
| would be interesting to know from which language these
| developers are actually migrating.
| IgorPartola wrote:
| Rust is also a systems language. I am still wrapping my
| mind around why it is so popular for so many end projects
| when its main use case and goals were basically writing a
| browser a maybe OS drivers.
|
| But that's precisely why it is good for developer tools.
| And it turns out people who write systems code are really
| damn good at writing tools code.
|
| As someone who cut my teeth on C and low level systems
| stuff I really ought to learn Rust one of these days but
| Python is just so damn nice for high level stuff and all my
| embedded projects still seem to require C so here I am,
| rustless.
| webstrand wrote:
| I write scripts in rust as a replacement for bash. Its
| really quite good at it. Aside from perl, its the only
| scripting language that can directly make syscalls. Its
| got great libraries for: parsing, configuration
| management, and declarative CLIs built right into it.
|
| Sure its a little more verbose than bash one-liners, but
| if you need any kind of error handling and recovery, its
| way more effective than bash and doesn't break when you
| switch platforms (i.e. mac/bsd utility incompatibilities
| with gnu utilities).
|
| My only complaint would be that dealing with OsString is
| more difficult than necessary. Way to much of the stdlib
| encourages programmers to just do "non-utf8 paths don't
| exist" and panic/ignore when encountering one. (Not a
| malady exclusive to rust, but I wish they'd gotten it
| right)
|
| Example I had handy: <https://gist.github.com/webstrand/9
| 45c738c5d60ffd7657845a654...>
| SAI_Peregrinus wrote:
| Paths are hard because they usually look like printable
| text, but don't have to be text. POSIX filenames are
| octet strings not containing 0x2F or 0x00. They aren't
| required to contain any "printable" characters, or even
| be valid text in any particular encoding. Most of the
| Rust stdlib you're thinking of is for handling text
| strings, but _paths aren 't text strings_. Python also
| has the same split between Pathlib paths & all other
| strings.
| aaronblohowiak wrote:
| If python's painpoints don't bother you enough (or you
| are already comfortable with all the workarounds,) then
| I'm not sure Rust will do much for you.
|
| What I like about Rust is ADTs, pattern matching,
| execution speed. The things that really give me
| confidence are error handling (right balance between "you
| can't accidentally ignore errors" of checked exceptions
| with easy escape hatches for when you want to YOLO,) and
| the rarity of "looks right, but is subtly wrong in
| dangerous ways" that I ran into a lot in dynamic
| languages and more footgun languages.
|
| Compile times suck.
| IgorPartola wrote:
| I rarely if ever encounter bugs that type checking would
| have fixed. Most common types of bugs for me are things
| like forgetting that two different code paths access a
| specific type of database record and when they do both
| need to do something special to keep data cohesive. Or
| things like concurrency. Or worst of all things like
| fragile subprocesses (ffmpeg does not like being
| controlled by a supervisor process). I think all in all I
| have encountered about a dozen bugs in Python that were
| due to wrong types over the past 17 years of writing code
| in this language. Maybe slightly more than that in JS.
| The reason I would switch is performance.
| habinero wrote:
| Same. I like the type hints -- they're nice reminders of
| what things are supposed to be -- but I've essentially
| ~never run into bugs caused by types, either. I've been
| coding professionally in Python for 10+ years at this
| point.
|
| It just doesn't come up in the web and devtools
| development worlds. Either you're dealing with user
| input, which is completely untrusted and has to be
| validated anyways, or you're passing around known
| validated data.
|
| The closest is maybe ETL pipelines, but type checking
| can't help there either since your entire goal is to
| wrestle with horrors.
| LtWorf wrote:
| You can validate user input with types using stuff like
| typedload (which i wrote) or similar runtime type
| checkers.
| aaronblohowiak wrote:
| For me, ADT's and pattern matching are about expressivity
| not type checking. Type checking really helps with
| refactoring quickly. If we're measuring experience with
| years, I was a rubyist for over a decade and have written
| python for another 5 years after that, so I have some
| dynamic language bona fides.
| johnisgood wrote:
| I mean, you can always replace Python with LuaJIT or
| Perl... or Nim... or Crystal... or Odin... or with
| Rust....
| Calavar wrote:
| Paul Graham said the same thing about Python 20 years ago
| [1], and back then it was true. But once a programming
| langauge hits mainstream, this ceases to be a good filter.
|
| [1] https://paulgraham.com/pypar.html
| jghn wrote:
| This is important. The benefit here isn't the language
| itself. It's the fact that you're pulling from an esoteric
| language. People should not overfit and feel that whichever
| language is achieving that effect today is special in this
| regard.
| discreteevent wrote:
| That was bullshit then and it's bullshit now but it sells
| very well to people who know a few programming languages (a
| lot of the people on this site)
| mkoubaa wrote:
| He was right. Python programmers are still the most likely
| to prioritize getting things done quickly.
| tyre wrote:
| This is a pretty broad generalization!
|
| The fastest iterating people engineers I've worked with
| often have a deep user focus rather than a language
| affiliation.
| rgoulter wrote:
| Eh.
|
| I think the cultural context has changed.
|
| In "python paradox", 'knows python' is an indication that
| the developer is interested in something technically
| interesting but otherwise impractical. Hence, it's a
| 'paradox' that you end up practically better off by
| selecting for something impractical.
|
| These days, Python is surely a practical choice, so
| doesn't really resemble the "interested in something
| technically interesting but impractical".
| bri3d wrote:
| It's an interesting debate. The flip side of this coin is
| getting hires who are more interested in the language or
| approach than the problem space and tend to either burn out,
| actively dislike the work at hand, or create problems that
| don't exist in order to use the language to solve them.
|
| With that said, Rust was a good language for this in my
| experience. Like any "interesting" thing, there was a
| moderate bit of language-nerd side quest thrown in, but
| overall, a good selection metric. I do think it's one of the
| best Rewrite it in X languages available today due to the
| availability of good developers with Rewrite in Rust project
| experience.
|
| The Haskell commentary is curious to me. I've used Haskell
| professionally but never tried to hire for it. With that
| said, the other FP-heavy languages that were popular
| ~2010-2015 were absolutely horrible for this in my
| experience. I generally subscribe to a vague notion that
| "skill in a more esoteric programming language will usually
| indicate a combination of ability to learn/plasticity and
| interest in the trade," however, using this concept, I had
| really bad experiences hiring both Scala and Clojure
| engineers; there was _way_ too much academic interest in
| language concepts and way too little practical interest in
| doing work. YMMV :)
| mannycalavera42 wrote:
| Clojure engineers not interested in doing work? That's
| surprising
| lll-o-lll wrote:
| When people say things like:
|
| > there was _way_ too much academic interest in language
| concepts and way too little practical interest in doing
| work.
|
| They are communicating something real, but perhaps
| misattributing the root cause.
|
| The purely abstract 'ideal' form of software development
| is unconstrained by business requirements. In this
| abstraction, _perfect_ software would be created to
| purely express an _idea_. Academia allows for this, and
| to a lesser extent some open source projects.
|
| In the real world, the creation of software must always
| be _subordinate_ to the goals of the business. The goals
| are the purpose, and the software is the means.
|
| Languages that are academically interesting,
| unsurprisingly, attract a greater preponderance of
| academically minded individuals. Of these, only a
| percentage have the desire or ability to let go of the
| pure abstract, and instead focus on the business domain.
| So it inevitably creates a management challenge; not an
| insurmountable one, but a challenge.
|
| Hence the simplified 'these people won't do the work!'.
| bri3d wrote:
| Yes, exactly this. I don't feel that I misattributed
| anything, but if I had to expound on the idea this is
| exactly how I would explain it.
| tikhonj wrote:
| If you're doing something forgettable, what makes you think
| the workaday Java or Python programmer would find it
| innately motivating?
|
| Alternately, if you have the sort of work or culture that
| taps into people's intrinsic motivation, why would that
| work worse with Haskell or Clojure programmers than anybody
| else?
|
| People are interested in different things along different
| dimensions. The way somebody is motivated by _what_ they
| 're doing and the way somebody is motivated by _how_ they
| 're doing it really don't seem all that correlated to me.
| psyclobe wrote:
| Got it so, because it is rust it is good.. 10-4!!
| nurettin wrote:
| > When a package says it requires python<4.0, uv ignores the
| upper bound and only checks the lower.
|
| I will bring popcorn on python 4 release date.
| yjftsjthsd-h wrote:
| If it's really not doing any upper bound checks, I could see it
| blowing up under more mundane conditions; Python includes
| breaking changes on .x releases, so I've had eg. packages
| _require_ (say) Python 3.10 when 3.11 /12 was current.
| dev_l1x_be wrote:
| I always bring popcorn on major version changes for any
| programming language. I hope Rust's never 2.0 stance holds.
| zahlman wrote:
| It would be popcorn-worthy regardless, given the rhetoric
| surrounding the idea in the community.
| ethin wrote:
| > Zero-copy deserialization. uv uses rkyv to deserialize cached
| data without copying it. The data format is the in-memory format.
| This is a Rust-specific technique.
|
| This (zero-copy deserialization) is not a rust-specific
| technique, so I'm not entirely sure why the author describes it
| as one. Any good low level language (C/C++ included) can do this
| from my experience.
| nemothekid wrote:
| Given the context of the article, I think "Rust specific" here
| means that "it couldn't be done in python".
|
| For example "No interpreter startup" is not specific to Rust
| either.
| kbd wrote:
| It's Rust vs Python in this case.
| woodruffw wrote:
| I think the framing in the post is that it's specific to Rust,
| relative to what Python packaging tools are otherwise written
| in (Python). It's not very easy to do zero-copy deserialization
| in pure Python, from experience.
|
| (But also, I think Rust can fairly claim that it's made zero-
| copy deserialization a lot easier and safer.)
| stefan_ wrote:
| I suppose it can fairly claim that now every other library
| and blog post invokes "zero-copy" this and that, even in the
| most nonsensical scenarios. It's a technique for when you can
| literally not afford the memory bandwidth, because you are
| trying to saturate a 100Gbps NIC or handling 8k 60Hz video,
| not for compromising your data serialization schemes
| portability for marketing purposes while all applications hit
| the network first, disk second and memory bandwidth never.
| woodruffw wrote:
| Many of the hot paths in uv involve an entirely locally
| cached set of distributions that need to be loaded into
| memory, very lightly touched/filtered, and then sunk to
| disk somewhere else. In those contexts, there are
| measurable benefits to not transforming your
| representation.
|
| (I'm agnostic on whether zero-copy "matters" in every
| single context. If there's no complexity cost, which is
| what Rust's abstractions often provide, then it doesn't
| really hurt.)
| vlovich123 wrote:
| You've got this backward. The vast majority of time due to
| spatial and temporal locality, in practice for any
| application you're actually usually doing CPU registers
| first, cache second, memory third, disk fourth, network
| cache fifth, and network origin sixth. So this stuff does
| actually matter for performance.
|
| Also, aside from memory bandwidth, there's a latency cost
| inherent in traversing object graphs - 0 copy techniques
| ensure you traverse that graph minimally, just what's
| needed to actually be accessed which is huge when you scale
| up. There's a difference between one network request and
| fetching 1 MB vs making 100 requests to fetch 10kib and
| this difference also appears in memory access patterns
| unless they're absorbed by your cache (not guaranteed for
| object graph traversal that a package manager would be
| doing).
| zahlman wrote:
| The point is that the packaging tool can analyze files from
| within the archives it downloads, without writing them to
| disk.
| zahlman wrote:
| I can't even imagine what "safety" issue you have in mind.
| Given that "zero-copy" apparently means "in-memory" (a
| deserialized version of the data necessarily cannot be the
| same object as the original data), that's not even difficult
| to do with the Python standard library. For example,
| `zipfile.ZipFile` has a convenience method to write to file,
| but writing to in-memory data is as easy as
| with zipfile.ZipFile(archive_name) as a: with
| a.open(file_name) as f, io.BytesIO() as b:
| b.write(f.read()) return b.getvalue()
|
| (That does, of course, copy data around _within memory_ ,
| but.)
| woodruffw wrote:
| > Given that "zero-copy" apparently means "in-memory" (a
| deserialized version of the data necessarily cannot be the
| same object as the original data), that's not even
| difficult to do with the Python standard library
|
| This is not what zero-copy means. Here's a working
| definition[1].
|
| Specifically, it's not just about keeping things in memory;
| copying in memory is normal. The goal is to _not_ make
| copies (or more precisely, what Rust would call "clones"),
| but to instead convey the original representation/views of
| that representation through the program's lifecycle where
| feasible.
|
| > a deserialized version of the data necessarily cannot be
| the same object as the original data
|
| rust-asn1 would be an example of a Rust library that
| doesn't make any copies of data unless you explicitly ask
| it to. When you load e.g. a Utf8String[2] in rust-asn1, you
| get a view into the original input buffer, not an
| intermediate owning object created from that buffer.
|
| > (That does, of course, copy data around within memory,
| but.)
|
| Yes, that's what makes it not zero-copy.
|
| [1]: https://rkyv.org/zero-copy-deserialization.html
|
| [2]:
| https://docs.rs/asn1/latest/asn1/struct.Utf8String.html
| zahlman wrote:
| > Yes, that's what makes it not zero-copy.
|
| Yeah, so you'd have to pass around the `BytesIO` instead.
|
| I know that zero-copy doesn't ordinarily mean what I
| described, but that seemed to be _how TFA was using it_ ,
| based on the logic in the rest of the sentence.
| woodruffw wrote:
| > Yeah, so you'd have to pass around the `BytesIO`
| instead.
|
| That wouldn't be zero-copy either: BytesIO is an I/O
| abstraction over a buffer, so it intentionally masks the
| "lifetime" of the original buffer. In effect, reading
| from the BytesIO creates new copies of the underlying
| data by design, in new `bytes` objects.
|
| (This is actually a great capsule example of why zero-
| copy design is difficult in Python: the Pythonic thing to
| do is to make lots of bytes/string/rich objects as you
| parse, each of which owns its data, which in turn means
| copies everywhere.)
| zahlman wrote:
| Fair. (You can `.getbuffer` but you still have to keep
| the underlying BytesIO object "open" somehow.)
|
| I'm not convinced this is going to bottleneck things,
| though.
|
| (On the flip side, I guess the OS is likely to cache any
| disk write in memory anyway.)
| carderne wrote:
| I'm just a casual observer of this thread, but I think
| you'd find it worthwhile to read up a bit on zero-copy
| stuff.
|
| It's ~impossible in Python (because you don't control
| memory) and hard in C/similar (because of use-after-
| free).
|
| Rust's borrow checker makes it easier, but it's still
| tricky (for non-trivial applications). You have to do all
| your transformations and data movements while only
| referencing the original data.
| SpaceNugget wrote:
| As a quick and kind of oversimplified example of what zero
| copy means, imagine you read the following json string from
| a file/the network/whatever: json =
| '{"user":"nugget"}' // from somewhere
|
| A simple way to extract json["user"] to a new variable
| would be to copy the bytes. In pythony/c pseudo code
| let user = allocate_string(6 characters) for i in
| range(0, 6) user[i] = json["user"][i] //
| user is now the string "nugget"
|
| instead, a zero copy strategy would be to create a string
| pointer to the address of json offset by 9, and with a
| length of 6. {"user":"nugget"}
| ^ ]end
|
| The reason this can be tricky in C is that when you call
| free(json), since user is a pointer to the same string that
| was json, you have effectively done free(user) as well.
|
| So if you use user after calling free(json), You have
| written a classic _memory safety_ bug called a "use after
| free" or UAF. Search around a bit for the insane number of
| use after free bugs there have been in popular software and
| the havoc they have wreaked.
|
| In rust, when you create a variable referencing the memory
| of another (user pointing into json) it keeps track of that
| (as a "borrow", so that's what the borrow checker does if
| you have read about that) and won't compile if json is
| freed while you still have access to user. That's the main
| memory safety issue involved with zero-copy deserialization
| techniques.
| landr0id wrote:
| They speak about "technique" but rkyv is a Rust-specific
| format. Could be an editing error or maybe they're suggesting
| it's more difficult in python.
| zahlman wrote:
| It seems to me more like a "LLM failing to grasp the true
| importance of a point" error.
| agumonkey wrote:
| very nice article, always good to get a review of what a "simple"
| looking tool does behind the scense
|
| about rust though
|
| some say a nicer language helps finding the right architecture
| (heard that about cpp veteran dropping it for ocaml, any
| attempted idea would take weeks in cpp, was a few days in ocaml,
| they could explore more)
|
| also the parallelism might be a benefit the language orientation
|
| enough semi fanboyism
| aswegs8 wrote:
| uv seems to be a pet peeve of HN. I always thought pipenv was
| good but yeah, seems like I was being ignorant
| aw1621107 wrote:
| > uv seems to be a pet peeve of HN.
|
| Unless I've been seeing very different submissions than you,
| "pet peeve" seems like the exact opposite of what is actually
| the case?
| VerifiedReports wrote:
| Indeed; I don't think he knows what "peeve" means...
| glaucon wrote:
| I too use pipenv unless there's a reason not to. I hope people
| use whatever works best for them.
|
| I feel that sometimes there's a desire on the part of those who
| use tool X that everyone should use tool X. For some types of
| technology (car seat belts, antibiotics...) that might be
| reasonable but otherwise it seems more like a desire for
| validation of the advocate's own choice.
| EdwardDiego wrote:
| My biggest complaint with pipenv is/was(?) that it's lockfile
| format only kept the platform identifiers of the platform you
| locked it on - so if you created it on Mac, then tried to
| install from the lockfile on a Linux box, you're building from
| source because it's only locked in wheels for MacOS.
|
| Poetry and uv avoid this issue.
| jlubawy wrote:
| Came here to ask about pipenv. As someone who does not use
| python other than for scripting, but also appreciates the
| reproduceability that pipenv provides, should I be using uv? My
| understanding is that pipenv is the better successor to venv
| and pip (combined), but now everyone is talking about uv so to
| be honest it's quite confusing.
|
| Edit: to add to what my understanding of pipenv is, the
| "standard/approved" method of package management by the python
| community, but in practice is it not? Is it now uv?
| epage wrote:
| > uv is fast because of what it doesn't do, not because of what
| language it's written in. The standards work of PEP 518, 517,
| 621, and 658 made fast package management possible. Dropping
| eggs, pip.conf, and permissive parsing made it achievable. Rust
| makes it a bit faster still.
|
| Isn't assigning out what all made things fast presumptive without
| benchmarks? Yes, I imagine a lot is gained by the work of those
| PEPs. I'm more questioning how much weight is put on dropping of
| compatibility compared to the other items. There is also no
| coverage for decisions influenced by language choice which likely
| influences "Optimizations that don't need Rust".
|
| This also doesn't cover subtle things. Unsure if rkyv is being
| used to reduce the number of times that TOML is parsed but TOML
| parse times do show up in benchmarks in Cargo and Cargo/uv's TOML
| parser is much faster than Python's (note: Cargo team member,
| `toml` maintainer). I wish the TOML comparison page was still up
| and showed actual numbers to be able to point to.
| zahlman wrote:
| > Isn't assigning out what all made things fast presumptive
| without benchmarks?
|
| We also have the benchmark of "pip now vs. pip years ago". That
| has to be controlled for pip version and Python version, but
| the former hasn't seen a lot of changes that are relevant for
| most cases, as far as I can tell.
|
| > This also doesn't cover subtle things. Unsure if rkyv is
| being used to reduce the number of times that TOML is parsed
| but TOML parse times do show up in benchmarks in Cargo and
| Cargo/uv's TOML parser is much faster than Python's (note:
| Cargo team member, `toml` maintainer). I wish the TOML
| comparison page was still up and showed actual numbers to be
| able to point to.
|
| This is interesting in that I wouldn't expect that the typical
| resolution involves a particularly large _quantity_ of TOML. A
| package installer really only needs to look at it at all when
| building from source, and part of what these standards have
| done for us is improve wheel coverage. (Other relevant PEPs
| here include 600 and its predecessors.) Although that has also
| largely been driven by education within the community, things
| like e.g. https://blog.ganssle.io/articles/2021/10/setup-py-
| deprecated... and https://pradyunsg.me/blog/2022/12/31/wheels-
| are-faster-pure-... .
| kibwen wrote:
| _> This is interesting in that I wouldn 't expect that the
| typical resolution involves a particularly large quantity of
| TOML._
|
| I don't know the details of Python's resolution algorithm,
| but for Cargo (which is where epage is coming from) a
| lockfile (which is encoded in TOML) can be somewhat large-
| ish, maybe pushing 100 kilobytes (to the point where I'm
| curious if epage has benchmarked to see if lockfile parsing
| is noticeable in the flamegraph).
| pnt12 wrote:
| But once you have a lock file there is no resolution
| needed, is there? It lists all needed libs and their
| versions. Given how toml is written, I imagine you can read
| it incrementally - once a lib section is parsed, you can
| download it in parallel, even if you didn't parse the whole
| file yet.
|
| (not sure how uv does it, just guessing what can be done)
| TheDong wrote:
| For whatever it's worth, the toml library uv uses doesn't
| support streaming parsing: https://github.com/toml-
| rs/toml/issues/326
| kibwen wrote:
| I'm not sure if it even makes sense for a TOML file to be
| "read incrementally", because of the weird feature of
| TOML (inherited from INI conventions) that allow tables
| to be defined in a piecemeal, out-of-order fashion.
| Here's an example that the TOML spec calls "valid, but
| discouraged": [fruit.apple]
| [animal] [fruit.orange]
|
| So the only way to know that you have all the keys in a
| given table is to literally read the entire file. This is
| one of those unfortunate things in TOML that I would
| honestly ignore if I were writing my own TOML parser,
| even if it meant I wasn't "compliant".
| zahlman wrote:
| I don't think that's worse than having to search an
| arbitrary distance for a matching closing bracket. There
| are tasks where you can start working knowing that a
| given array in the data might be appended to later
| (similarly for objects).
| kibwen wrote:
| It's worse than having to parse a matching bracket,
| because any context where you have an item defined via
| nested brackets is going to be a subset of this use case.
| But yes, that doesn't mean you couldn't do some
| theoretical eager processing, but it's going to be
| context dependent. For example, consider a Cargo.toml
| file, where we've processed the `features` key for a
| given dependency. Is it safe to begin compiling that
| dependency with the given set of features before we
| finish parsing the file? No, because there might be a
| `default-features=false` key that applies to this
| dependency later in the file. In a format where tables
| weren't allowed to be split, the mere act of parsing a
| single, self-contained dependency entry would be enough
| to know for certain that no such `default-features` key
| exists. Not all potential keys are going to require this
| sort of consideration, but it could be a footgun
| depending on the semantics of your schema.
| epage wrote:
| TOML as a format doesn't make sense for streaming
|
| - Tables can be in any order, independent of heirarchy
|
| - keys can be dotted, creating subtables in any order
|
| On top of that, most use cases for the format are not
| benefitted by streaming.
| epage wrote:
| For Cargo,
|
| - synchronization operations are implicit so we need to
| re-resolve to confirm the lockfile is still valid. We
| could take some short cut but it would require re-
| implementing some logic
|
| - dependency resolution only uses `Cargo.toml` for local
| and git dependencies. Registry dependencies have a json
| summary of what content is relevant for dependency
| resolution. Cargo parses nearly every locked package's
| `Cargo.toml` to know how to build it.
| epage wrote:
| Lockfiles aren't an issue. It is all the dependencies
| themselves.
| krick wrote:
| To be fair, the whole post isn't very good IMO, regardless of
| ChatGPT involvement, and it's weird how some people seem to
| treat it like some kind of revelation.
|
| I mean, _of course_ it wasn 't specifically Rust that made it
| fast, it's really a banal statement: you need only very
| moderate serious programming experience to know, that rewriting
| legacy system from scratch can make it faster even if you
| rewrite it in a "slower" language. There have been C++ systems
| that became faster when rewritten in Python, for god's sake.
| That's what makes system a "legacy" system: it does a ton of
| things and nobody really knows what it does anymore.
|
| But when listing things that made uv faster it really mentions
| some silly things, among others. Like, it doesn't parse
| pip.conf. Right, sure, the secret of uv's speed lies in not-
| parsing other package manager's config files. Great.
|
| So all in all, yes, no doubt that hundreds of little things
| contributed into making uv faster, but listing a few dozens of
| them (surely a non-exhaustive lists) doesn't really enable you
| to make any conclusions about the relative importance of
| different improvements whatsoever. I suppose the mentioned
| talk[0] (even though it's more than a year old now) would serve
| as a better technical report.
|
| [0] https://www.youtube.com/watch?v=gSKTfG1GXYQ
| pecheny wrote:
| The content is nice and insightful! But God I wish people stopped
| using LLMs to 'improve' their prose... Ironically, some day we
| might employ LLMs to re-humanize texts that had been already
| massacred.
| laidoffamazon wrote:
| Interestingly I didn't catch this, I liked it for not looking
| LLM written!
| yunohn wrote:
| "Why this matters" being the final section is a guaranteed
| give away, among innumerable others.
| rick_dalton wrote:
| I realized once I was in the "optimizations that dont need
| rust" section. Specifically "This is concurrency, not
| language magic."
| dkmar wrote:
| Yup. The author has now swapped that part out for "Any
| language can do this."
|
| Just commenting to preempt any comments telling you that
| the article doesn't say this.
| yunohn wrote:
| I used to rely on this, and still mostly do - but you'd
| be surprised how quickly this has entered the normal
| vernacular! I hear people using it in conversation
| unprompted all the time.
| yunohn wrote:
| I have reached a point where any AI smell (of which this
| articles has many) makes me want to exit immediately. It feels
| tortuous to my reading sensibilities.
|
| I blame fixed AI system prompts - they forcibly collapse all
| inputs into the same output space. Truly disappointing that
| OpenAI et all have no desire to change this before everything
| on the internet sounds the same forever.
| fleebee wrote:
| You're probably right about the latter point, but I do wonder
| how hard it'd be to mask the default "marketing copywriter"
| tone of the LLM by asking it to assume some other tone in
| your prompt.
|
| As you said, reading this stuff is taxing. What's more, this
| is a daily occurrence by now. If there's a silver lining,
| it's that the LLM smells are so obvious at the moment; I can
| close the tab as soon as I notice one.
| SatvikBeri wrote:
| > do wonder how hard it'd be to mask the default "marketing
| copywriter" tone of the LLM by asking it to assume some
| other tone in your prompt.
|
| Fairly easy, in my wife's experience. She repeatedly got
| accused of using chatgpt in her original writing (she's not
| a native english speaker, and was taught to use many of the
| same idioms that LLMs use) until she started actually using
| chatgpt with about two pages of instructions for tone to
| "humanize" her writing. The irony is staggering.
| mattkevan wrote:
| It's pretty easy. I've written a fairly detailed guide to
| help Claude write in my tone of voice. It also coaxes it to
| avoid the obvious AI tells such as 'It's not X it's Y'
| sentences, American English and overuse of emojis and em
| dashes.
|
| It's really useful for taking my first drafts and cleaning
| them up ready for a final polish.
| cmrx64 wrote:
| https://ember.dev 's deeper pages (not the blog, but the
| "resumelike" project pages) was written by claude with
| guidance and a substantial corpus of my own writing and i
| still couldn't squash out all the GPTisms in the
| generation passes. probably net waste of time, for me,
| for writing.
| yunohn wrote:
| It's definitely partially solved by extensive custom
| prompting, as evidenced by sibling comments. But that's a
| lot of effort for normal users and not a panacea either.
| I'd rather AI companies introduce noise/randomness
| themselves to solve this at scale.
| twoodfin wrote:
| I don't think that's a solution.
|
| The problem isn't the surface tics--em dashes, short
| exclamatory sentences, lists of three, "Not X: Y!".
|
| Those are symptoms of the deep, statistically-built
| tissue of LLM "understanding" of "how to write a
| technical blog post".
|
| If you randomize the surface choices you're effectively
| running into the same problem Data did on _Star Trek: The
| Next Generation_ when he tried to get the computer to
| give him a novel Sherlock Holmes mystery on the holodeck.
| The computer created a nonsense mishmash of characters,
| scenes, and plot points from stories in its data bank.
|
| Good writing uses a common box of metaphorical &
| rhetorical tools in novel ways to communicate novel
| ideas. By design, LLMs are trying to avoid true
| (unpredictable) novelty! Thus they'll inevitably use
| these tools to do the reverse of what an author should be
| attempting.
| efilife wrote:
| I also don't read AI slop. It's disrespectful to any reader.
| Der_Einzige wrote:
| Read our paper on de-slopping LLM outputs. It's far more than
| simply all having the same fixed AI system prompts. It's an
| overuse of post-training and contempt for pre-training.
|
| https://arxiv.org/pdf/2510.15061
| captn3m0 wrote:
| The author' blog was on HN a few days ago as well for an
| article on SBOMs and Lockfiles. They've done a lot of work in
| the supply-chain security side and are clearly knowledgeable,
| and yet the blog post got similarly "fuzzified" by the LLM.
| zahlman wrote:
| There are a handful of things in TFA that, while not outright
| false, are sloppy enough that I'd expect someone
| knowledgeable to know/explain better.
| pnt12 wrote:
| I didn't notice that - can you give some examples?
| collinmanderson wrote:
| Some issues I noticed were:
|
| > PEP 658 went live on PyPI in May 2023. uv launched in
| February 2024. uv could be fast because the ecosystem
| finally had the infrastructure to support it. A tool like
| uv couldn't have shipped in 2020. The standards weren't
| there yet.
|
| In 2020 you could still have a whole bunch of performance
| wins before the PEP 658 optimization. There's also the
| "HTTP range requests" optimization which is the next best
| thing. (and the uv tool itself is really good with "uv
| run" and "uv python".)
|
| > What uv drops: Virtual environments required. pip lets
| you install into system Python by default. uv inverts
| this, refusing to touch system Python without explicit
| flags. This removes a whole category of permission checks
| and safety code.
|
| pip also refuses to touch system Python without explicit
| flags?
|
| For uv, there are flags that allow it, so it doesn't
| really "removes a whole category of permission checks and
| safety code"? uv has "permission checks and safety code"
| to check if it's system python? I don't think uv has
| "dropped" anything here.
|
| > Optimizations that don't need Rust: Python-free
| resolution. pip needs Python running to do anything.
|
| This seems to me to be implying that python is inherently
| slow, so yes, this optimization requires a faster
| language? Or maybe I don't get the full point.
|
| > Where Rust actually matters: No interpreter startup.
| ... uv is a single static binary with no runtime to
| initialize.
|
| This one's pretty petty/pedantic, but "Rust technically
| has a very lightweight runtime." https://users.rust-
| lang.org/t/does-rust-have-a-runtime/11406...
| NewsaHackO wrote:
| To me, unless it is egregious, I would be very sensitive to
| avoid false positives before saying something is LLM _aided_.
| If it is clearly just slop, then okay, but I definitely think
| there is going to be a point where people claim well-written,
| straightforward posts as LLM aided. (Or even the opposite,
| which already happens, where people purposely put errors in
| prose to seem genuine).
| DrawTR wrote:
| Editing the post to switch five "it's X not Y"s[1] is pretty
| disappointing. I wish people were more clear with their
| disclosure of LLM editing.
|
| [1]:
| https://github.com/andrew/nesbitt.io/commit/0664881a524feac4...
| efilife wrote:
| This is terrible. So disrespectful. It's baffling how someone
| can do this under their own name
| NewsaHackO wrote:
| I recsind my previous statement. Also, people have to stop
| putting everything on github.
| stephendause wrote:
| Why? To me, hosting previous versions of an article in a
| public git repo adds transparency. Or perhaps you are
| talking about GitHub specifically?
| Der_Einzige wrote:
| You're supposed to also remove the fancy UTF-8 quotes that
| people can't normally type, the EM dashes, and reorder
| sentences/clauses because the paragraph level "template" slop
| is really obvious to people who use these models all the
| time. (I'm also pretty sure that the UTF-8 shenanigans with
| LLM responses was done _very_ on purpose by those who have a
| vested interest in making it easier for mass surveillance of
| written communication.)
|
| Or, use the "deep research" mode for writing your prose
| instead. It's far less sloppy in how it writes.
|
| These people are amateurs at humanizing their writing.
| yieldcrv wrote:
| > Ironically, some day we might employ LLMs to re-humanize
| texts
|
| I heard high school and college students are doing this
| routinely so their papers don't get flagged as AI
|
| this is whether they used an LLM for the whole assignment or
| wrote it themselves, has to get pass through a "re-humanizing"
| LLM either way just to avoid drama
| 4k93n2 wrote:
| there is going to be a point where people have read so much
| slop that they will start regurgitating the same style without
| even realising it. or we could already be at that point
| mepiethree wrote:
| I definitely found the thesis insightful. The actual content
| stopped feeling insightful to me in the "What uv drops"
| section, where cut features were all listed as if they had
| equal weight, all in the same breathless LLM style
| Der_Einzige wrote:
| We wrote the paper on how to deslop your LLM outputs and if you
| use our factory de-slopped versions of gemma3 you don't have to
| worry about this, similarly if you use our antislop sampler,
| your LLM outputs will look very close to human.
|
| https://arxiv.org/abs/2510.15061
| ec109685 wrote:
| The article info is great, but why do people put up with LLM
| ticks and slop in their writing? These sentences add no value and
| treats the reader as stupid.
|
| > This is concurrency, not language magic.
|
| > This is filesystem ops, not language-dependent.
|
| Duh, you literally told me that the previous sentence and 50
| million other times.
| aurumque wrote:
| This kind of writing goes deeper than LLM's, and reflects a
| decline in both reading ability, patience, and attention.
| Without passing judgement, there are just more people now who
| benefit from repetition and summarization embedded directly in
| the article. The reader isn't 'stupid', just burdened.
| twoodfin wrote:
| Indeed, I am coming around in the past few weeks to
| realization and acceptance that the LLM editorial voice is a
| benefit to an order of magnitude more hn readers than those
| (like us) for whom it is ice pick in the nostril stuff.
|
| Oh well, all I can do is flag.
| hallvard wrote:
| Great post, but the blatant chatgpt-esque feel hits hard... Don't
| get me wrong, I love astral! and the content, but...
| hallvard wrote:
| Reading the other replies here makes it really obvious that
| this is some LLM's writing. Maybe even all of it...
| skywhopper wrote:
| This is great to read because it validates my impression that
| Python packaging has always been a tremendous overengineered
| mess. Glad to see someone finally realized you just need a simple
| standard metadata file per package.
| zahlman wrote:
| It has been realized in the Python community for a very long
| time. But there have been years of debate over the contents and
| formatting, and years of trying to figure out how to convince
| authors and maintainers to do the necessary work on their end,
| and years of trying to make sure the ecosystem doesn't explode
| from trying to remove legacy support.
|
| There are still separate forms of metadata for source packages
| and pre-compiled distributions. This is necessary because of
| all the weird idiosyncratic conditional logic that might be
| necessary in the metadata for platform-specific dependencies.
| Some projects are reduced to figuring out the final metadata at
| build time, while building on the user's machine, because
| that's the only way to find out enough about the user's machine
| to make everything work.
|
| It really isn't as straightforward as you'd expect, largely
| because Python code _commonly_ interfaces to compiled code in
| _several_ different languages, and end users expect this to
| "just work", including on Windows where they don't have a
| compiler and might not know what that is.
|
| See https://pypackaging-native.github.io/ for the general
| flavour of it.
| looneysquash wrote:
| I don't have any real disagreement with any of the details the
| author said.
|
| But still, I'm skeptical.
|
| If it is doable, the best way to prove it is to actually do it.
|
| If no one implements it, was it ever really doable?
|
| Even if there is no technical reason, perhaps there is a social
| one?
| stevemk14ebr wrote:
| What are you talking about, this all exists
| zahlman wrote:
| I guess you mean doing the things in Python that are supposedly
| doable from Python.
|
| Yeah, to a zeroth approximation that's my current main project
| (https://github.com/zahlman/paper). Of course, I'm just some
| rando with apparently serious issues convincing myself to put
| in regular unpaid work on it, but I _can see_ in broad strokes
| how everything is going to work. (I 'm not sure I would have
| thought about, for example, hard-linking files when installing
| them from cache, without uv existing.)
| VerifiedReports wrote:
| So... will uv make Python a viable cross-platform utility
| solution?
|
| I was going to learn Python for just that (file-conversion
| utilities and the like), but everybody was so down on the messy
| ecosystem that I never bothered.
| zahlman wrote:
| It has been viable for a long time, and the kinds of projects
| you describe are likely well served by the standard library.
| oblio wrote:
| It hasn't been viable and you'd know if you tried to deploy
| Python scripts to Windows users and maintain/update them over
| longer periods of time.
| pseudosavant wrote:
| I write all of my scripts in Python with PEP 723 metadata and
| run them with `uv run`. Works great on Windows and Linux for
| me.
| IshKebab wrote:
| Yes, uv basically solves the terrible Python tooling situation.
|
| In my view that was by far the biggest issue with Python - a
| complete deal-breaker really. But uv solves it pretty well.
|
| The remaining big issues are a) performance, and b) the import
| system. uv doesn't do anything about those.
|
| Performance may not be an issue in some cases, and the import
| system is ... tolerable if you're writing "a python project".
| If you're writing some other project and considering using
| Python for its scripting system, e.g. to wrangle multiple build
| systems or whatever than the import mess is a bigger issue and
| I would thing long and hard before picking it over Deno.
| VerifiedReports wrote:
| Thanks! I don't really think about importing stuff (which
| maybe I should), because I assume I'll have to write any
| specialized logic myself. So... your outlook is encouraging.
| pwdisswordfishy wrote:
| > Some of uv's speed comes from Rust. But not as much as you'd
| think. Several key optimizations could be implemented in pip
| today: [...] Python-free resolution
|
| Umm...
| andy99 wrote:
| I remain baffled about these posts getting excited about uv's
| speed. I'd like to see a real poll but I personally can't imagine
| people listing speed as one of the their top ten concerns about
| python package managers. What are the common use cases where the
| delay due to package installation is at all material?
|
| Edit to add: I use python daily
| pants2 wrote:
| The biggest benefit is in CI environments and Docker images and
| the like where all packages can get reinstalled on every run.
| gordonhart wrote:
| `poetry install` on my dayjob's monolith took about 2 minutes,
| `uv sync` takes a few seconds. Getting 2 minutes back on every
| CI job adds up to a lot of time saved
| toenail wrote:
| The speed is nice, but I switched because uv supports "pip
| compile" from pip-tools, and it is better at resolving
| dependencies. Also pip-tools uses (used?) internal pip methods
| and breaks frequently because of that, uv doesn't.
| recov wrote:
| Docker builds are a big one, at least at my company. Any tool
| that reduces wait time is worth using, and uv is an amazing
| tool that removes that wait time. I take it you might not use
| python much as it solves almost every pain point, and is fast
| which feels rare.
| stavros wrote:
| I can run `uvx sometool` without fear because I know that it'll
| take a few seconds to create a venv, download all the
| dependencies, and run the tool. uv's speed has literally
| changed how I work with Python.
| quectophoton wrote:
| I wouldn't say without fear, since you're one typo away from
| executing a typo-squatted malicious package.
|
| I do use it on CI/CD pipelines, but I wouldn't dare type uvx
| commands myself on a daily basis.
| stavros wrote:
| uvx isn't more risky than `pip install`, which is what I
| used before.
| pnt12 wrote:
| But with pip you only need to be careful on install -
| with uvx you need to be careful forever.
|
| I'm a big fan of uv, but don't like that part of uvx.
|
| (makes me wonder if a small wrapper can do this - safe
| uvx, or suvx for short)
| stavros wrote:
| I generally tend to let the shell autocomplete, so I
| don't type it out every time, but I see your point. If I
| use a program more than once or twice, I install it.
| rsyring wrote:
| As a multi decade Python user, uv's speed is "life changing".
| It's a huge devx improvement. We lived with what came before,
| but now that I have it, I would never want to go back and it's
| really annoying to work on projects now that aren't using it.
| thraxil wrote:
| Working heavily in Python for the last 20 years, it absolutely
| was a big deal. `pip install` has been a significant percentage
| of the deploy time on pretty much every app I've ever deployed
| and I've spent countless hours setting up various caching
| techniques trying to speed it up.
| SatvikBeri wrote:
| Setting up a new dev instance took 2+ hours with pip at my
| work. Switching to uv dropped the Python portion down to <1
| minute, and the overall setup to 20 minutes.
|
| A similar, but less drastic speedup applied to docker images.
| techbruv wrote:
| At a previous job, I recall updating a dependency via poetry
| would take on the order of ~5-30m. God forbid after 30 minutes
| something didn't resolve and you had to wait another 30 minutes
| to see if the change you made fixed the problem. Was not an
| enjoyable experience.
|
| uv has been a delight to use
| pxc wrote:
| > updating a dependency via poetry would take on the order of
| ~5-30m. God forbid after 30 minutes something didn't resolve
| and you had to wait another 30 minutes to see if the change
| you made fixed the problem
|
| I'd characterize that as unusable, for sure.
| patrick91 wrote:
| for me it's being able to do `uv run whatever` and always know
| I have the correct dependencies
|
| (also switching python version is so fast)
| pseudosavant wrote:
| I avoided Python for years, especially because of package and
| environment management. Python is now my go to for projects
| since discovering uv, PEP 723 metadata, and LLMs' ability to
| write Python.
| adammarples wrote:
| It's annoying. Do you use poetry? Pipenv? It's annoying.
| IshKebab wrote:
| Do you still remain baffled after the many replies that people
| actually do like their tooling to be not dog slow like pip is?
| VorpalWay wrote:
| CI: I changed a pipeline at work from pip and pipx to uv, it
| saved 3 minutes on a 7 minute pipeline. Given how
| oversubscribed our runners are, anything saving time is a big
| help.
|
| It is also really nice when working interactivly to have snappy
| tools that don't take you out of the flow more than absolutely
| more than necessary. But then I'm quite sensitive to this, I'm
| one of those people who turn off all GUI animations because
| they waste my time and make the system feel slow.
| zahlman wrote:
| It's not just about delays being "material"; waiting on the
| order of seconds for a venv creation (and knowing that this is
| because of pip bootstrapping itself, when it _should_ just be
| able to install cross-environment instead of having to wait
| until 2022 for an ugly, limited hack to support that) is
| _annoying_.
|
| But small efficiencies do matter; see e.g.
| https://danluu.com/productivity-velocity/.
| ExoticPearTree wrote:
| Build jobs where you have a lot of dependencies. Those GHA
| minutes go brrrr.
| optionalsquid wrote:
| Speed is one of the main reasons why I keep recommending uv to
| people I work with, and why I initially adopted it: Setting up
| a venv and installing requirements became so much faster.
| Replacing pipx and `uv run` for single-file scripts with
| external dependencies, were additional reasons. With nox adding
| uv support, it also became much easier and much faster to test
| across multiple versions of Python
| blibble wrote:
| conda can take an hour to tell you your desired packages are
| unsatisifiable
|
| saying that, other than the solver, most of what uv does is
| always going to be IO bound
| curiousgal wrote:
| People criticising conda's solver prove they haven't used it
| in years.
| optionalsquid wrote:
| You can also use pixi[1] if you want conda with uv's
| solver, that does appears to be faster than the mamba
| solver. Though the main reasons I recommend pixi, are that
| it doesn't have a tendency to break random stuff due to
| polluting your environment by default, and that it does a
| much better job of making your environments reproducible,
| among another benefits
|
| [1] https://pixi.sh/
| morshu9001 wrote:
| One weird case where this mattered to me, I wanted pip to
| backtrack to find compatible versions of a set of deps, and it
| wasn't done after waiting a whole hour. uv did the same thing
| in 5 minutes. This might be kinda common because of how many
| Python repos out there don't have pinned versions in
| dependencies.txt.
| scotty79 wrote:
| For me speed was irrelevant however uv was the first Python
| project manger with tolerable ui that I encountered. I never
| before done any serious development in Python because I just
| refused dealing with venvs requirements.txt and whatever. When
| a script used a dependancy or another Python version I
| installed it system wide. uv is perfectly usable, borderline
| pleasent. But I'm sure the speed helps.
| riazrizvi wrote:
| Probably 90% of ppl commenting here are focused on managing
| their own Python installs and mostly don't care about speed. uv
| seems to be designed for enterprise, for IT management of
| company wide systems, and this post is, I'm guessing, a little
| promotional astroturfing. For most of us, uv solves a low
| priority problem.
| nojs wrote:
| It's a major factor in build times for Django containers for
| example.
| VeejayRampay wrote:
| it is absolutely a _huge_ deal, I suspect you work daily in
| python but with a small number of repositories that dont change
| too often
| zahlman wrote:
| I've talked about this many times on HN this year but got beaten
| to the punch on blogging it seems. Curses.
|
| ... Okay, after a brief look, there's still lots of room for me
| to comment. In particular:
|
| > pip's slowness isn't a failure of implementation. For years,
| Python packaging required executing code to find out what a
| package needed.
|
| This is largely refuted by the fact that pip is _still_ slow,
| _even when installing from wheels_ (and getting PEP 600 metadata
| for them). Pip is actually still slow even when doing _nothing_.
| (And when you create a venv and allow pip to be bootstrapped in
| it, that bootstrap process takes in the high 90s percent of the
| total time used.)
| didibus wrote:
| There's an interesting psychology at play here as well, if you
| are a programmer that chooses a "fast language" it's indicative
| of your priorities already, it's often not much the language, but
| that the programmer has decided to optimize for performance from
| the get go.
| bastawhiz wrote:
| > When a package says it requires python<4.0, uv ignores the
| upper bound and only checks the lower. This reduces resolver
| backtracking dramatically since upper bounds are almost always
| wrong. Packages declare python<4.0 because they haven't tested on
| Python 4, not because they'll actually break. The constraint is
| defensive, not predictive.
|
| This is kind of fascinating. I've never considered runtime upper
| bound requirements. I can think of compelling reasons for lower
| bounds (dropping version support) or exact runtime version
| requirements (each version works for exact, specific CPython
| versions). But now that I think about it, it seems like upper
| bounds solve a hypothetical problem that you'd never run into in
| practice.
|
| If PSF announced v4 and declared a set of specific changes, I
| think this would be reasonable. In the 2/3 era it was definitely
| reasonable (even necessary). Today though, it doesn't actually
| save you any trouble.
| wging wrote:
| I think the article is being careful not to say uv ignores
| _all_ upper bound checks, but specifically 4.0 upper bound
| checks. If a package says it requires python < 3.0, that's
| still super relevant, and I'd hope for uv to still notice and
| prevent you from trying to import code that won't work on
| python 3. Not sure what it actually does.
| breischl wrote:
| I read the article as saying it ignores all upper-bounds, and
| 4.0 is just an example. I could be wrong though - it seems
| ambiguous to me.
|
| But if we accept that it currently ignores any upper-bounds
| checks greater than v3, that's interesting. Does that imply
| that once Python 4 is available, uv will slow down due to
| needing to actually run those checks?
| VorpalWay wrote:
| Are there any plans to actually make a 4.0 ever? I remember
| hearing a few years ago that after the transition to 3.0,
| the core devs kind of didn't want to repeat that mess ever
| again.
|
| That said, even if it does happen, I highly doubt that is
| the main part of the speed up compared to pip.
| zahlman wrote:
| There are indeed not any such plans.
| bastawhiz wrote:
| I think there's a future where we get a 4.0, but it's not
| any time soon. I think they'd want an incredibly
| compelling backwards-incompatible feature before ripping
| that band-aid off. It would be setting up for a decade of
| transition, which shouldn't be taken lightly.
| cmrx64 wrote:
| That would deliver a blow to the integrity of the rest of
| that section because those sorts of upper bound constraints
| immediately reducible to "true" cannot cause backtracking
| of any kind.
| bastawhiz wrote:
| uv doesn't support <3.0 (I think the minimum is 3.8?) so it
| would be difficult for that to be relevant. But for pip,
| obviously yes.
| unethical_ban wrote:
| The problem: The specification is binary. Are you compatible or
| not?
|
| That is unanswerable now, whether a python package will be
| compatible with a version that is not released.
|
| Having an ENUM like [compatible, incompatible, untested] at the
| least would fix this.
| ofek wrote:
| > pip could implement parallel downloads, global caching, and
| metadata-only resolution tomorrow. It doesn't, largely because
| backwards compatibility with fifteen years of edge cases takes
| precedence.
|
| pip is simply difficult to maintain. Backward compatibility
| concerns surely contribute to that but also there are other
| factors, like an older project having to satisfy the needs of
| modern times.
|
| For example, my employer (Datadog) allowed me and two other
| engineers to improve various aspects of Python packaging for
| nearly an entire quarter. One of the items was to satisfy a few
| long-standing pip feature requests. I discovered that the cross-
| platform resolution feature I considered most important is
| basically incompatible [1] with the current code base.
| Maintainers would have to decide which path they prefer.
|
| [1]: https://github.com/pypa/pip/issues/13111
| zahlman wrote:
| > pip is simply difficult to maintain. Backward compatibility
| concerns surely contribute to that but also there are other
| factors, like an older project having to satisfy the needs of
| modern times.
|
| Backwards compatibility is the one thing that prevents the code
| in an older project from being replaced with a better approach
| _in situ_. It cannot be _more_ difficult than a rewrite, except
| that rewrites (arguably including my project) may hold
| themselves free to skip hard legacy cases, at least initially
| (they might not be relevant by the time other code is ready).
|
| (I would be interested in hearing from you about UX designs for
| cross-platform resolution, though. Are you just imagining
| passing command-line flags that describe the desired target
| environment? What's the use case exactly -- just making a
| .pylock file? It's hard to imagine cross-platform
| _installation_....)
| eviks wrote:
| > Every code path you don't have is a code path you don't wait
| for.
|
| No, every code path you don't execute is that. Like
|
| > No .egg support.
|
| How does that explain anything if the egg format is obsolete and
| not used?
|
| Similar with spec strictness fallback logic - it's only slow if
| the packages you're installing are malformed, otherwise the logic
| will not run and not slow you down.
|
| And in general, instead of a list of irrelevant and potentially
| relevant things would be great to understand some actual time
| savings per item (at least those that deliver the most speedup)!
|
| But otherwise great and seemingly comprehensive list!
| zahlman wrote:
| > No, every code path you don't execute is that.
|
| Even in compiled languages, binaries have to get loaded into
| memory. For Python it's much worse. On my machine:
| $ time python -c 'pass' real 0m0.019s user
| 0m0.013s sys 0m0.006s $ time pip --version >
| /dev/null real 0m0.202s user 0m0.182s
| sys 0m0.021s
|
| Almost all of that extra time is either the module import
| process or garbage collection at the end. Even with cached
| bytecode, the former requires finding and reading from
| literally hundreds of files, deserializing via `marshal.loads`
| and then running top-level code, which includes creating
| objects to represent the functions and classes.
|
| It used to be even worse than this; in recent versions, imports
| related to Requests are deferred to the first time that an
| HTTPS request is needed.
| eviks wrote:
| > binaries have to get loaded into memory.
|
| Unless memory mapped by the OS with no impact on runtime for
| unused parts?
|
| > imports related to Requests are deferred
|
| Exactly, so again have no impact?
| zahlman wrote:
| > Unless memory mapped by the OS with no impact on runtime
| for unused parts?
|
| Yeah, this is presumably why a no-op `uv` invocation on my
| system takes ~50 ms the first time and ~10 ms each other
| time.
|
| > Exactly, so again have no impact?
|
| Only if your invocation of pip manages to avoid an Internet
| request. Note: pip will make an Internet request if you try
| to install a package by symbolic name _even if it already
| has the version it wants in cache_ , because its cache is
| an HTTP cache rather than a proper download cache.
|
| But even then, there will be hundreds of imports mainly
| related to Rich and its dependencies.
| eviks wrote:
| > Only if your invocation of pip manages to avoid an
| Internet request.
|
| Yes it does, by definition, the topic of discussion is
| the impact of _unused_ code paths? How is http cache
| relevant here? That 's a used path!
| zahlman wrote:
| I got confused by the direction of the discussion.
|
| My original point was that Requests imports in pip _used
| to not_ be deferred like that, so you would pay for them
| _up front, even if_ they turned out to be irrelevant.
| (But also they are relevant more often than they should
| be, i.e. the deferral system doesn 't work as well as it
| should.)
|
| Part of the reason you pay for them is to run _top-level_
| code (to create function and class objects) that are
| irrelevant to what the program is actually _doing_. But
| another big part is the cost of actually locating the
| files, reading them, and deserializing bytecode from
| them. This happens at import time even if you don 't
| invoke any of the functionality.
| cmrx64 wrote:
| rtld does a lot of work even in "static" binaries to
| rewrite relocations even in "unused parts" of any PIE
| (which should be all of them today) and most binaries need
| full dyld anyway.
| efilife wrote:
| this shit is ChatGPT-written and I'm really tired of it. If I
| wanted to read chatgpt I would have asked it myself. Half of the
| article are nonsensical repeated buzzwords thrown in for
| absolutely no reason
| IshKebab wrote:
| Mmm I don't buy it. Not many projects use setup.py now anyway and
| pip is still super slow.
|
| > Plenty of tools are written in Rust without being notably fast.
|
| This also hasn't been my experience. Most tools written in Rust
| _are_ notably fast.
| zahlman wrote:
| > Not many projects use setup.py now anyway and pip is still
| super slow.
|
| Yes, but that's _still_ largely not because of being written in
| Python. The architecture is really just that bad. Any run of
| pip that touches the network will end up importing _more than
| 500_ modules and a lot of that code will simply not be used.
|
| For example, one of the major dependencies is Rich, which
| includes things like a 3600-entry mapping of string names to
| emoji; Rich in turn depends on Pygments which normally includes
| a bunch of rules for syntax highlighting in dozens of
| programming languages (but this year they've finished trimming
| those parts of the vendored Pygments).
|
| Another thing is that pip's cache is an HTTP cache. It
| literally doesn't know how to access its own package download
| cache without hitting the network, and it does that access
| through wrappers that rely on cachecontrol and Requests.
| IshKebab wrote:
| > Any run of pip that touches the network will end up
| importing more than 500 modules and a lot of that code will
| simply not be used.
|
| That's a property of Python though. The fact that it isn't
| compiled (and that importing is very slow).
|
| > a 3600-entry mapping of string names to emoji
|
| Which can easily be zero-cost in Rust.
|
| > It literally doesn't know how to access its own package
| download cache without hitting the network
|
| This is the only example you've given that actually fits with
| your thesis.
| zahlman wrote:
| > That's a property of Python though. The fact that it
| isn't compiled (and that importing is very slow).
|
| Bytecode compilation is compilation.
|
| There are many things that could be used to improve import
| speed that I never even see discussed, let alone
| implemented.
|
| But most importantly, pip _doesn 't need to have all these
| modules imported_. They already proved they could defer the
| Requests imports; but the actual network calls aren't that
| hard to do with the standard library anyway. (As nice as it
| would be to have Requests _in_ the standard library, but I
| digress.) Most of the stuff it imports up-front from Rich
| will go entirely unused.
|
| > Which can easily be zero-cost in Rust.
|
| Which is irrelevant to the point.
|
| > This is the only example you've given that actually fits
| with your thesis.
|
| No. My thesis is that pip doesn't have to be the way it is
| in order to actually solve the problem of installing Python
| packages. Everything I mentioned is an example of a thing
| pip doesn't have to do in order to install packages, and
| slows it down unnecessarily.
| scottlamb wrote:
| Mine either. Choosing Rust by no means guarantees your tool
| will be fast--you can of course still screw it up with poor
| algorithms. But I think most people who choose Rust do so in
| part because they aspire for their tool to be "blazing fast".
| Memory safety is a big factor of course, but if you didn't care
| about performance, you might have gotten that via a GCed (and
| likely also interpreted or JITed or at least non-LLVM-backend)
| language.
| IshKebab wrote:
| Yeah sometimes you get surprisingly fast Python programs or
| surprisingly slow Rust programs, but if you put in a normal
| amount of effort then in the vast majority of cases Rust is
| going to be 10-200x faster.
|
| I actually rewrote a non-trivial Python program in Rust once
| because it was so slow (among other reasons), and got a 50x
| speedup. It was mostly just running regexes over logs too,
| which is the sort of thing Python people say is an ideal case
| (because it's mostly IO or implemented in C).
| ggm wrote:
| Some of these speed ups looked viable to backport into pip
| including parallel download, delayed .pyc, ignore egg, version
| checks.
|
| Not that I'd bother since uv does venv so well. But, "it's not
| all rust runtime speed" implies pip could be faster too.
| robertclaus wrote:
| At Plotly we did a decent amount of benchmarking to see how much
| the different defaults `uv` uses lead to its performance. This
| was necessary so we could advise our enterprise customers on the
| transition. We found you lost almost all of the speed gains if
| you configured uv behave as much like pip as you could. A trivial
| example is the precompile flag, which can easily be 50% of pips
| install time for a typical data science venv.
|
| https://plotly.com/blog/uv-python-package-manager-quirks/
| zahlman wrote:
| The precompilation thing was brought up to the uv team several
| months ago IIRC. It doesn't make as much of a difference for uv
| as for pip, because when uv is told to pre-compile it can
| parallelize that process. This is easily done in Python (the
| standard library even provides rudimentary support, which
| Python's own Makefile uses); it just isn't in pip yet (I
| understand it will be soon).
| w10-1 wrote:
| I like the implication that we can have an alternative to uv
| speed-wise, but I think reliability and understandability are
| more important in this context (so this comment is a bit off-
| topic).
|
| What I want from a package manager is that it just works.
|
| That's what I mostly like about uv.
|
| Many of the changes that made speed possible were to reduce the
| complexity and thus the likelihood of things not working.
|
| What I don't like about uv (or pip or many other package
| managers), is that the programmer isn't given a clear mental
| model of what's happening and thus how to fix the inevitable
| problems. Better (pubhub) error messages are good, but it's rare
| that they can provide specific fixes. So even if you get 99%
| speed, you end up with 1% perplexity and diagnostic black boxes.
|
| To me the time that matters most is time to fix problems that
| arise.
| zahlman wrote:
| > the programmer isn't given a clear mental model of what's
| happening and thus how to fix the inevitable problems.
|
| This is a priority for PAPER; it's built on a lower-level API
| so that programmers _can_ work within a clear mental model, and
| I will be trying my best to communicate well in error messages.
| pkaodev wrote:
| AI slop
| rvz wrote:
| TLDR: Because Rust.
|
| This entire AI generated article with lots of text just to just
| say the obvious.
| zahlman wrote:
| That conclusion is largely false, and is not what the article
| says.
| punnerud wrote:
| My favorite speed up trick: " HTTP range requests for metadata.
| Wheel files are zip archives, and zip archives put their file
| listing at the end. uv tries PEP 658 metadata first, falls back
| to HTTP range requests for the zip central directory, then full
| wheel download, then building from source. Each step is slower
| and riskier. The design makes the fast path cover 99% of cases.
| None of this requires Rust."
| zahlman wrote:
| > None of this requires Rust.
|
| Indeed. As demonstrated by the fact that pip has been doing
| exactly the same for years.
|
| Part of the reason things are improving is that "tries PEP 658
| metadata first" is more likely to succeed, and at some point
| build tools may have become more aware of how pip expects the
| zip to be organized (see https://packaging.python.org/en/latest
| /specifications/binary...), and way more projects ship wheels
| (because the manylinux standard has improved, and because pure-
| Python devs have become aware of things like
| https://pradyunsg.me/blog/2022/12/31/wheels-are-faster-
| pure-...).
| simonw wrote:
| This post is excellent. I really like reading deep dives like
| this that take a complex system like uv and highlight the unique
| design decisions that make it work so well.
|
| I also appreciate how much credit this gives the many previous
| years of Python standards processes that enabled it.
|
| Update: I blogged more about it here, including Python
| recreations of the HTTP range header trick it uses and the
| version comparison via u64 integers:
| https://simonwillison.net/2025/Dec/26/how-uv-got-so-fast/
| BiteCode_dev wrote:
| Other design decisions that made uv fast:
|
| - uncompressing packages while they are still being downloaded,
| in memory, so that you only have to write to disk once
|
| - design of its own locking format for speed
|
| But yes, rust is actually making it faster because:
|
| - real threads, no need for multi-processing
|
| - no python VM startup overhead
|
| - the dep resolution algo is exactly the type of workload that is
| faster in a compiled language
|
| Source, this interview with Charlie Marsh:
| https://www.bitecode.dev/p/charlie-marsh-on-astral-uv-and-th...
|
| The guy has a lot of interesting things to say.
| zzzeek wrote:
| > real threads, no need for multi-processing
|
| parallel downloads don't need multi-processing since this is an
| IO bound usecase. asyncio or GIL-threads (which unblock on IO)
| would be perfectly fine. native threads will eventually be the
| default also.
| BiteCode_dev wrote:
| Indeed, but unzipping while downloading do. Analysing
| multiple metadata files and exporting lock data as well.
|
| Now I believe unzip releases the GIL already so we could
| already benefit from that and the rest likely don't dominate
| perfs.
|
| But still, rust software is faster on average than python
| software.
|
| After all, all those things are possible in python, and yet
| we haven't seen them all in one package manager before uv.
|
| Maybe the strongest advantage of rust, on top of very clean
| and fast default behaviors, is that it attracts people that
| care about speed, safety and correctness. And those devs are
| more likely to spend time implementing fast software.
|
| Thought the main benefit of uv is not that it's fast. It's
| very nice, and opens more use cases, but it's not the killer
| feature.
|
| The killer feature is, being a stand alone executable, it
| bypasses all python bootstrapping problems.
|
| Again, that could technically be achieved in python, but
| friction is a strong force.
| zzzeek wrote:
| > Maybe the strongest advantage of rust, on top of very
| clean and fast default behaviors, is that it attracts
| people that care about speed, safety and correctness. And
| those devs are more likely to spend time implementing fast
| software.
|
| people who have this opinion should use Rust, not Python,
| at all. if Python code does not have sufficient speed,
| safety, and correctness for someone, it should not be used.
| Python's tools should be written in Python.
|
| > The killer feature is, being a stand alone executable, it
| bypasses all python bootstrapping problems.
|
| I can't speak for windows or macs but on Linux, system
| pythons are standard, and there is no "bootstrapping
| problem" using well known utilities that happen to be
| written in Python.
| zahlman wrote:
| > uncompressing packages _while they are still being
| downloaded_
|
| ... but the archive directory is at the end of the file?
|
| > no python VM startup overhead
|
| This is about 20 milliseconds on my 11-year-old hardware.
| BiteCode_dev wrote:
| HTTP range strikes again.
|
| As for 20 ms, if you deal with 20 dependencies in parallel,
| that's 400ms just to start working.
|
| Shaving half a second on many things make things fast.
|
| Althought as we saw with zeeek in the other comment, you
| likely don't need multiprocessing since the network stack and
| unzip in the stdlib release the gil.
|
| Threads are cheaper.
|
| Maybe if you'd bundle pubgrub as a compiled extension, you
| coukd get pretty close to uv's perf.
| zahlman wrote:
| Why are you starting a separate Python process for each
| dependency?
| collinmanderson wrote:
| Using the -S ("isolated") flag can maybe cut startup in half.
| didip wrote:
| If UV team has a spare time, they should rewrite Python in Rust
| without any of the legacy baggage.
| hk1337 wrote:
| It's fast because it sucks the life force from bad developers to
| make them into something good.
|
| Jokes aside...
|
| I really like uv but also really like mise and I cannot seem to
| get them to work well together.
| Onavo wrote:
| Why? They are pretty compatible. Just set the venv in the
| project's mise.toml are you are good to go. Mise will activate
| it automatically when you change into the project directory.
| hk1337 wrote:
| I believe I was trying it the other way around. I installed
| uv and python with mise but uv still created a
| .python_version file and using the one installed in the
| system instead of what was in mise
| zzzeek wrote:
| > pip could implement parallel downloads, global caching, and
| metadata-only resolution tomorrow. It doesn't, largely because
| backwards compatibility with fifteen years of edge cases takes
| precedence. But it means pip will always be slower than a tool
| that starts fresh with modern assumptions.
|
| what does backwards compatibility have to do with parallel
| downloads? or global caching? The metadata-only resolution is the
| only backwards compatible issue in there and pip can run without
| a setup.py file being present if pyproject.toml is there.
|
| Short answer is most, or at least a whole lot, of the
| improvements in uv could be integrated into pip as well
| (especially parallelizing downloads). But they're not, because
| there is uv instead, which is also maintained by a for-profit
| startup. so pip is the loser
| orliesaurus wrote:
| The most surprising part of uv's success to me isn't Rust at all,
| it's how much speed we "unlocked" just by finally treating Python
| packaging as a well-specified systems problem instead of a pile
| of historical accidents. If uv had been written in Go or even
| highly optimized CPython, but with the same design decisions (PEP
| 517/518/621/658 focus, HTTP range tricks, aggressive wheel-first
| strategy, ignoring obviously defensive upper bounds, etc.), I
| strongly suspect we'd be debating a 1.3x vs 1.5x speedup instead
| of a 10x headline -- but the conversation here keeps collapsing
| back to "Rust rewrite good/bad." That feels like cargo-culting
| the toolchain instead of asking the uncomfortable question: why
| did it take a greenfield project to give Python the package
| manager behavior people clearly wanted for the last decade?
| edoceo wrote:
| Consensus building and figuring out what was actually needed?
|
| Someone on this site said most tech problems are people
| problems - this feels like one.
|
| Greenfield mostly solves the problem because it's all new
| people.
| morshu9001 wrote:
| I can't find the quote for this, but I remember Python
| maintainers wanted package installing and management to be
| separate things. uv did the opposite, and instead it's more
| like npm.
| MBCook wrote:
| Do you remember the reason? I spend most of my time in the
| Java and JS ecosystems where one tool does both jobs.
|
| In my mind they're pretty heavily linked. But that may be
| based on not experiencing the opposite. At least not as far
| as I can remember.
| morshu9001 wrote:
| Separation of concerns. They just wanted pip to be a good
| installer and let package managers* use pip. But uv
| didn't end up doing that either.
|
| * or workflow tools as they're called here
| https://packaging.python.org/en/latest/guides/tool-
| recommend...
| zahlman wrote:
| This probably represents it fairly accurately, though I
| had to search for it and haven't watched:
| https://www.youtube.com/watch?v=QzxDIKbOp_4
|
| Travis Oliphant is a founder of Anaconda and one of the
| most important people behind NumPy, SciPy etc.
| baby_souffle wrote:
| I largely agree but don't want to entirely discount the effect
| that using a compiled language had.
|
| At least in my limited experience, the selling point with the
| most traction is that you don't already need a working python
| install to get UV. And once you have UV, you can just go!
|
| If I had a dollar for every time I've helped somebody untangle
| the mess of python environment libraries created by an
| undocumented mix of python delivered through the distributions
| package management versus native pip versus manually
| installed...
|
| At least on paper, both poetry and UV have a pretty similar
| feature set. You do however need a working python environment
| to install and use poetry though.
| mkoubaa wrote:
| 1000% this. uv is trivially installable and is completely
| unrelated to installations of python.
| eru wrote:
| I wonder how much Rust's default to statically link almost
| everything helped here? That should make deployment of uv
| even easier?
| crote wrote:
| I don't think this makes a meaningful difference. The
| installation is a `curl | sh`, which downloads a tarball,
| which gets extracted to some directory in $PATH.
|
| It currently includes two executables, but having it
| contain two executables _and_ a bunch of .so libraries
| would be a fairly trivial change. It only gets messy when
| you want it to make use of system-provided versions of
| the libraries, rather than simply vendoring them all
| yourself.
| vlovich123 wrote:
| It gets mess not just in that way but also someone can
| have a weird LD_LIBRARY_PATH that starts to have
| problems. Statically linking drastically simplifies
| distribution and you've had to have distributed 0
| software to end users to believe otherwise. The only
| platform this isn't the case for is Apple because they
| natively supported app bundles. I don't know if flat pack
| solves the distribution problem because I've not seen a
| whole lot of it in the ecosystem - most people seem to
| generally still rely on the system package manager and
| commercial entities don't seem to really target flat
| pack.
| nh2 wrote:
| When you're shipping software, you have full control over
| LD_LIBRARY_PATH. Your entry point can be e.g. a shell
| script that sets it.
|
| There is not so much difference between shipping a
| statically linked binary, and a dynamically linked binary
| that brings its own shared object files.
|
| But if they are equivalent, static linking has the
| benefit of simplicity: Why create and ship N files that
| load each other in fancy ways, when you can do 1 that
| doesn't have this complexity?
| vlovich123 wrote:
| That's precisely my point. It's insanely weird to have a
| shell script to setup the path for an executable binary
| that can't do it for itself. I guess you could go the
| RPATH route but boy have I only experienced pain from
| that.
| mkoubaa wrote:
| RPATH is painless if you don't try to be clever
| zahlman wrote:
| If I want to install Python on Windows and start using pip,
| I grab an installer from python.org and follow a wizard. On
| Linux, I almost certainly already have it anyway.
|
| If I want to bootstrap from uv on Windows, the _simplest_
| option offered involves Powershell.
|
| Either way, I can write quite a bit with just the standard
| library before I have to understand what uv really is (or
| what pip is). At that point, yes, the pip UX is quite a bit
| messier. But I already have Python, and pip itself was also
| trivially installable (e.g. via the standard library
| `ensurepip`, or from a Linux system package manager -- yes,
| still using the command line, but this hypothetical is
| conditioned on being a Linux user).
| 112233 wrote:
| Not many normal people want to install python. Instead,
| author of the software they are trying to use wants them
| to install python. So they follow readme, download
| windows installer as you say, pip this pipx, pipx that
| conda, conda this requirements.txt, and five minutes
| later they have magic error telling that tensorflow
| version they are installing is not compatible with
| pytorch version they are installing or some such.
|
| The aftertaste python leaves is lasting-disgusting.
| zahlman wrote:
| Scenarios like that are simply not realistic. Besides
| which, multiple solutions exist for bundling Python with
| an application.
| jacquesm wrote:
| Scenarios like that occur daily. I do quite a bit of
| software development and whenever I come across something
| that really needs python I mentally prepare for a day of
| battle with the various (all subtly broken) package
| managers, dependency hell and circular nonsense to the
| point that I am also ready to give up on it after a day
| of trying.
|
| Just recently: a build of a piece of software that itself
| wasn't written in python but that urgently needed a very
| particular version of it with a whole bunch of
| dependencies that refused to play nice with Anaconda for
| some reason (which in spite of the fact that it too is
| becoming less reliable is probably still the better one).
| The solution? Temporarily move andaconda to a backup
| directory, remove the venv activation code from .bashrc
| and compile the project, then restore everything to the
| way it was before (which I need it to be because I have
| some other stuff on the stove that is built using python
| because there isn't anything else).
|
| And let's not go into bluetooth device support in python,
| anything involving networking that is a little bit off
| the beaten path and so on.
| zahlman wrote:
| > Scenarios like that occur daily. I do quite a bit of
| software development and whenever I come across something
| that really needs python I mentally prepare for a day of
| battle with the various (all subtly broken) package
| managers, dependency hell and circular nonsense to the
| point that I am also ready to give up on it after a day
| of trying.
|
| Please name a set of common packages that causes this
| problem reliably.
| jacquesm wrote:
| You're getting a bit boring, and are not arguing in good
| faith. "Reliably"... as per your definition I guess. You
| have now made 60(!!!) comments in this thread questioning
| everything and everybody without ever once accepting that
| other people's experiences do not necessarily have to
| match your own. If you did some reading rather than just
| writing you'd have seen that I gave a very specific
| example right in this thread. You are now going on my
| blocklist because I really don't have time or energy to
| argue with language zealots.
| the__alchemist wrote:
| Nailed it. Python was my first language, but I dread
| having to install someone else's Python software!
| firesteelrain wrote:
| Traditional Windows install didn't include things
| Microsoft doesn't make. But, any PC distributor could
| always include Python as part of their base Windows
| install with all the other stuff that bloats the typical
| third party Windows installs. They don't which indicates
| the market doesn't want it. Your indictment of the lack
| of Python out of the box is less on Windows than on the
| "distro" served by PC manufacturers
| crote wrote:
| So basically, it avoids the whole chicken-and-egg problem.
| With UV you've simply _always_ got "UV -> project Python
| 1.23 -> project". UV is your dependency manager, and your
| Python is _just another dependency_.
|
| With other dependency managers you end up with "system Python
| 3.45 -> dep manager -> project Python 1.23 -> project". Or
| worse, "system Python 1.23 -> dep manager -> project Python
| 1.23 -> project". And of course there will be people who read
| about the problem and install their _own_ Python manager, so
| they end up with a "system Python -> virtualenv Python ->
| poetry Python -> project" stack. Or the other way around, and
| they'll end up installing their project dependencies
| globally...
| zahlman wrote:
| Sorry, but that is simply incorrect, on many levels.
|
| Virtual environments are the fundamental way of setting up
| a Python project, _whether or not_ you use uv, which
| _creates and manages them for you_. And these virtual
| environments can freely either use or not use the system
| environment, _whether or not_ you use uv to create them. It
| 's literally a single-line difference in the `pyvenv.cfg`
| file, which is a standard required part of the environment
| (see https://peps.python.org/pep-0405/), created _whether
| or not_ you use uv.
|
| _Most of the time you don 't need_ a different Python
| version from the system one. When you do, uv can install
| one for you, but it doesn't change what your dependency
| chain actually is.
|
| Python-native tools like Poetry, Hatch etc. also work by
| managing standards-defined virtual environments (which can
| be created using the standard library, and you don't even
| have to bootstrap pip into them if you don't want to) _in
| fundamentally the same way_ that uv does. Some of them can
| even grab Python builds for you the same way that uv does
| (of course, uv doesn 't need a "system Python" to exist
| first). "system Python -> virtualenv Python -> poetry
| Python -> project" is complete nonsense. The "virtualenv
| Python" _is_ the system Python -- either a symlink or a
| stub executable that launches that Python -- and the
| project will be installed into that virtual environment. A
| tool like Poetry might use the system Python directly, or
| it might install into its own separate virtual environment;
| but either way it doesn 't cause any actual complication.
|
| Anyone who "ends up installing their project dependencies
| globally" has simply not read and understood Contemporary
| Python Development 101. In fact, anyone doing this on a
| reasonably new Linux has _gone far out of the way to avoid_
| learning that, by forcefully bypassing multiple warnings
| (such as described in https://peps.python.org/pep-0668/).
|
| _No matter what your tooling_ , the only sensible "stack"
| to end up with, for almost any project, is: base Python
| (usually the system Python but may be a separately
| installed Python) -> virtual environment (into which both
| the project and its dependencies are installed). The base
| Python provides the standard library; often there will be
| no third-party libraries, and even if there are they will
| usually be cut off intentionally. (If your Linux comes with
| pre-installed third-party libraries, they exist primarily
| to service tools that are part of your Linux distribution;
| you may be able to use them for some useful local hacking,
| but they are not appropriate for serious, publishable
| development.)
|
| Your tooling sits parallel to, and isolated from, that as
| long as it is literally anything other than pip -- and
| _even with pip you can_ have that isolation (it 's flawed
| but it works for common cases; see for example
| https://zahlman.github.io/posts/2025/02/28/python-
| packaging-... for how I set it up using a vendored copy of
| pip provided by Pipx), and _have been able to for three
| years now_.
| fragmede wrote:
| > has simply not read and understood Contemporary Python
| Development 101.
|
| They haven't. At the end of the day, they just want their
| program to work. You and I can design a utopian packaging
| system, but the physics PhD with a hand-me-down windows
| laptop and access to her university's Linux research
| cluster don't care about python other than it has a PITA
| library situation that UV addresses.
| zahlman wrote:
| If they are not developers, it's the developer's
| responsibility to fix that. The developers have many
| options available for this.
| Perseids wrote:
| You misunderstand. The _physicists_ are developing their
| _own_ software to analyze their experimental data. They
| typically have little software development experience,
| but there is seldom someone more knowledgeable available
| to support them. Making matters worse, they often are not
| at all interested in software development and thus also
| don 't invest the time to learn more than the absolute
| minimum necessary to solve their current problem, even if
| it could save them a lot of time in the long run. (Even
| though I find the situation frustration, I can't say I
| don't relate, given that I feel the same way about
| LaTeX.)
| aragilar wrote:
| Honestly, they should be using conda (if they're working
| on their laptops) and the cluster package manager
| otherwise.
| jacquesm wrote:
| Conda has slowly but surely gone down the drain as well.
| It used to be bullet proof but there too you now get
| absolutely unsolvable circular dependencies.
| fluorinerocket wrote:
| I haven't ever experienced this yet, what packages were
| involved?
| jacquesm wrote:
| Good question, I can't backtrack right now but it was
| apmplanner that I had to compile from source, and it
| contains some python that gets executed during the build
| process (I haven't seen it try to run it during normal
| execution yet).
|
| Probably either one of python-serial python-pexpect
| judging by the file dates, and neither of these are so
| exciting that there should have been any version
| conflicts at all.
|
| And the only reason I had to rebuild it at all was due to
| _another_ version conflict in the apm distribution that
| expects a particular version of pixbuf to be present on
| the system and all hell breaks loose if it isn 't, and
| you can't install that version on a modern system because
| that breaks other packages.
|
| It is insane how bad all this package management crap is.
| The GNU project and the linux kernel are the only ones
| that have never given me any trouble.
| raincole wrote:
| They're not applications developers, but they need to
| write code. That's the whole point. Python is popular
| within academia because it replaces R/Excel/VB.Net, not
| Java/C++.
| oblio wrote:
| Or they can give them a self contained binary that dodges
| 80% of these support issues because hear me out - and
| we've known this for 60+ years:
|
| Users do NOT read the manual. Users ignore warnings.
| Users double click "AnnaKurnikovaNude.exe".
| whakim wrote:
| > Most of the time you don't need a different Python
| version from the system one.
|
| Except for literally anytime you're collaborating with
| anyone, ever? I can't even begin to imagine working on a
| project where folks just use whatever python version
| their OS happens to ship with. Do you also just ship the
| latest version of whatever container because most of the
| time nothing has changed?
| Mawr wrote:
| This is more or less the thinking that got us into the
| mess Python packaging is.
|
| I, as a user, do not care whatsoever about any of this.
| At all. If you're explaining "virtual environments",
| you've lost the plot.
|
| Compiled languages got this right. The dev creates a
| binary and I as a user simply run it. That's it. That's
| the holy grail.
|
| It's good to see at last someone in the Python space got
| their ducks in a row and we've finally got a sensible
| tool.
| zahlman wrote:
| > the selling point with the most traction is that you don't
| already need a working python install to get UV. And once you
| have UV, you can just go!
|
| I still genuinely do not understand why this is a serious
| selling point. Linux systems commonly already provide (and
| heavily depend upon) a Python distribution which is perfectly
| suitable for creating virtual environments, and Python on
| Windows is provided by a traditional installer following the
| usual idioms for Windows end users. (To install uv on Windows
| I would be expected to use the PowerShell equivalent of a
| curl | sh trick; many people trying to learn to use Python on
| Windows have to be taught what cmd.exe is, never mind
| PowerShell.) If anything, new Python-on-Windows users are
| getting tripped up by the moving target of attempts to make
| it _even easier_ (in part because of things Microsoft messed
| up when trying to coordinate with the CPython team; see for
| example https://stackoverflow.com/questions/58754860/cmd-
| opens-windo... when it originally happened in Python 3.7).
|
| > If I had a dollar for every time I've helped somebody
| untangle the mess of python environment libraries created by
| an undocumented mix of python delivered through the
| distributions package management versus native pip versus
| manually installed...
|
| Sure, but that has everything to do with not understanding
| (or caring about) virtual environments (which are
| fundamental, and used by uv under the hood because there is
| really no viable alternative), and nothing to do with getting
| Python in the first place. I also don't know what you mean
| about "native pip" here; it seems like you're conflating the
| Python installation process with the package installation
| process.
| oefrha wrote:
| Linux systems commonly already provide an outdated system
| Python you don't want to use, and it can't be used to
| create a venv of a version you want to use. A single Python
| version for the entire system fundamentally doesn't work
| for many people thanks to shitty compat story in the vast
| ecosystem.
|
| Even languages with great compat story are moving to
| support multi-toolchains natively. For instance, go 1.22 on
| Ubuntu 24.04 LTS is outdated, but it will automatically
| download the 1.25 toolchain when it seems go 1.25.0 in
| go.mod.
| zahlman wrote:
| > Linux systems commonly already provide an outdated
| system Python you don't want to use
|
| Even with LTS Ubuntu updated only at EOL, Python will not
| be EOL most of the time.
|
| > A single Python version for the entire system
| fundamentally doesn't work for many people thanks to
| shitty compat story in the vast ecosystem.
|
| My experience has been radically different. Everyone is
| trying their hardest to provide wheels for a wide range
| of platforms, and all the most popular projects succeed.
| Try adding `--only-binary=:all:` to your pip invocations
| and let me know the next time that actually causes a
| failure.
|
| Besides which, I was very specifically talking about the
| user story for people who are just learning to program
| and will use Python for it. Because _otherwise this
| problem is trivially solved by anyone competent_. In
| particular, building and installing Python from source is
| just the standard configure / make / make install dance,
| and it Just Works. I have done it many times and never
| needed any help to figure it out even though it was the
| first thing I tried to build from C source after
| switching to Linux.
| vanviegen wrote:
| Sure. You do a source install every time you require a
| python version newer than system python.
|
| I'll be using uv for that though, as I'll be using it for
| its superior package management anyway.
| oefrha wrote:
| For much of the ML/scientific ecosystem, you're lucky to
| get all your deps working with the latest minor version
| of Python six months to a year after its release. Random
| ML projects with hundreds to thousands of stars on GitHub
| may only work with a specific, rather ancient version of
| Python.
|
| > Because otherwise this problem is trivially solved by
| anyone competent. In particular, building and installing
| Python from source is just the standard configure / make
| / make install dance, and it Just Works. I have done it
| many times and never needed any help to figure it out
| even though it was the first thing I tried to build from
| C source after switching to Linux.
|
| I compiled the latest GCC many times with the standard
| configure / make / make install dance when I just started
| learning *nix command line. I even compiled gmp, mpfr,
| etc. many times. It Just Works. Do you compile your GCC
| every time before you compile your Python? Why not? It
| Just Works.
| klibertp wrote:
| > Why not?
|
| Time. CPython compiles in a few minutes on an
| underpowered laptop. I don't recall last time I compiled
| GCC, but I had to compile LLVM and Clang recently, and it
| took significantly longer than "a few minutes" on a high-
| end desktop.
| zahlman wrote:
| > Random ML projects with hundreds to thousands of stars
| on GitHub may only work with a specific, rather ancient
| version of Python.
|
| Can you name some?
|
| > Do you compile your GCC every time before you compile
| your Python? Why not? It Just Works.
|
| If I needed a different version of GCC to make Python
| work, then probably, yes. But I haven't yet.
|
| Just like I barely ever need a different version of
| Python. I keep several mainly so that I can test/verify
| compatibility of my own code.
| firesteelrain wrote:
| Why not just use a Python container rather than rely on
| having the latest binary installed on the system? Then
| venv inside the container. That would get you the "venv
| of a version" that you are referring to
| adrian17 wrote:
| It's more complex and heavier than using uv. I see
| docker/vm/vagrant/etc as something as something I reach
| for when the environment I want is too big, too fancy or
| too nondeterministic to manually set up locally; but the
| entire point is that "plain Python with some
| dependencies" really shouldn't qualify as any of these
| (just like build environment for a random Rust library).
|
| Also, what do you do when you want your to locally test
| your codebase across many Python versions? Do you keep
| track of several different containers? If you start
| writing some tool to wrap that, you're back at square
| one.
| firesteelrain wrote:
| > what do you do when you want your to locally test your
| codebase across many Python versions?
|
| I haven't found that there was any breakage across Python
| 3.x. Python 2.x to 3.x yes.
|
| Anyways, this all could be wrapped in a CICD job and
| automated if you wanted to test across all versions.
| baq wrote:
| 'we can't ship the Python version you want for your OS so
| we'll ship the whole OS' is a solution, but the 'we
| can't' part was embarrassing in 2015 already.
| firesteelrain wrote:
| GP is referring to LTS versions though
|
| Many Linux distributions ship Python. Alpine and DSL
| don't. You can add it to Alpine. If you want the latest,
| you install it.
| rmah wrote:
| Our firm uses python extensively and the virtual
| environment for every script or script is ... difficult.
| We have dozens of python scripts running for team
| research and in production, from small maintenance tools
| to rather complex daemons. Add to that the hundreds of
| Jupyter notebooks used by various people. Some have a
| handful of dependencies, some dozens of dependencies.
| While most of those scripts/notebooks are only used by a
| handful of people, many are used company-wide.
|
| Further, we have a rather largish set of internal
| libraries most of our python programs rely on. And some
| of those rely on external 3rd party API's (often REST).
| When we find a bug or something changes, more often than
| not, we want to roll out the changed internal lib so that
| all programs that use it get the fix. Having to get
| everyone to rebuild and/or redeploy everything is a non-
| starter as many of the people involved are not primarily
| software developers.
|
| We _usually_ install into the system dirs and have a
| dependency problem _maybe_ once a year. And it 's usually
| trivially resolved (the biggest problem was with some
| google libs which had internally inconsistent
| dependencies at one point).
|
| I can understand _encouraging_ the use of virtual
| environments, but this movement towards _requiring_ them
| ignores what, I think, is a very common use case. In
| short, no one way is suitable for everyone.
| firesteelrain wrote:
| But in your case if you had a vanilla even just a
| standard, hardened RHEL image then you can run as many
| container variations as you want and not be impacted by
| host changes. Actually the host can stay pretty static.
|
| You would have a standard container image
| baby_souffle wrote:
| > Why not just use a Python container rather than rely on
| having the latest binary installed on the system?
|
| Sometimes this is the right answer. Sometimes
| docker/podman/runc are not an option nor would the
| headache of volumes/mounts/permissions/hw-pass-through be
| worth the additional mess.
|
| It is hard to over-state how delightful putting `uv` in
| the shebang is:
|
| in `demo.py`: #!/usr/bin/env -S uv run
| # /// script # requires-python = ">=3.13"
| print("hello, world")
|
| Then `chmod +x demo.py; ./demo.py`
|
| At no point did I have a detour to figure out why
| `python` is symlinked to `python3` unless I am in some
| random directory where there is a half-broken `conda`
| environment...
| firesteelrain wrote:
| Yes, PATH-driven interpreter selection is the source of
| the detours. uv eliminates interpreter ambiguity but
| requires uv as a prerequisite. This improves portability
| inside environments that standardize uv; it's not
| "portable to machines with nothing installed."
|
| Though, this isn't about avoiding installs; it's about
| making the one install (uv) the only thing you have to
| get right, instead of debugging whatever python means
| today.
|
| I was advocating for containers as the "hard isolation /
| full stack" solution which eliminate host interpreter
| ambiguity and OS drift by running everything inside a
| pinned image. But you do need podman and have the
| permissions set right on it.
| CamouflagedKiwi wrote:
| > Linux systems commonly already provide an outdated
| system Python you don't want to use
|
| They can be a bit long in the tooth, yes, but from past
| experience another Python version I don't want to use is
| anything ending in .0, so I can cope with them being a
| little older.
|
| That's in quite a bit of contrast to something like Go,
| where I will happily update on the day a new version
| comes out. Some care is still needed - they allow
| security changes particularly to be breaking, but at
| least those tend to be deliberate changes.
| Nextgrid wrote:
| It's not just greenfield-ness but the fact it's a _commercial_
| endeavor (even if the code is open-source).
|
| Building a _commercial_ product means you pay money (or
| something they equally value) to people to do your bidding. You
| don 't have to worry about politics, licensing, and all the
| usual FOSS-related drama. You pay them to set their opinions
| aside and build what _you_ want, not what _they_ want (and if
| that doesn 't work, it just means you need to offer more
| money).
|
| In this case it's a company that believes they can make a
| "good" package manager they can sell/monetize somehow and so
| built that "good" package manager. Turns out it's at least
| _good enough_ that other people now like it too.
|
| This would never work in a FOSS world because the project will
| be stuck in endless planning as everyone will have an opinion
| on how it should be done and nothing will _actually_ get done.
|
| Similar story with systemd - all the bitching you hear about it
| (to this day!) is the stuff that would've happened during its
| development phase had it been developed as a typical FOSS
| project and ultimately made it go nowhere - but instead it's
| one guy that just did what he wanted and shared it with the
| world, and enough other people liked it and started building
| upon it.
| eru wrote:
| > You don't have to worry about politics, licensing, and all
| the usual FOSS-related drama. You pay them to set their
| opinions aside and build what you want, not what they want
| (and if that doesn't work, it just means you need to offer
| more money).
|
| Money is indeed a great lubricator.
|
| However, it's not black-and-white: office politics is a long
| standing term for a reason.
| Nextgrid wrote:
| Office politics happen when people determine they can get
| more money by engaging in politics instead of working. This
| is just an indicator people aren't being paid enough money
| (since people politicking around is detrimental to the
| company, it is better off paying them whatever it takes for
| them _not_ to engage in such behavior). "You get what you
| pay for" applies yet again.
| xvector wrote:
| Hard disagree, most of my coworkers make well north of
| $1M and office politics is at an all time high.
|
| I believe office politics happens when there are simply
| too many people at a company or org.
| optionalsquid wrote:
| Office politics happen when the number of people at an
| office exceeds 2
| calenti wrote:
| Exceeds 1. Politics is the craft of influence. And,
| debatably, there's a politic even when population size=1,
| between your subconscious instinctive mind (eat the
| entire box of donuts) versus your conscious mind (don't
| spike your blood sugar).
| Nextgrid wrote:
| I think too many people happens because a company would
| rather hire 10 "market rate" people than 3 well-
| compensated ones. Headcount inflation dilutes
| responsibility and rewards, so even if one of the "market
| rate" guys does the best work possible they won't get
| rewarded proportionally... so if hard work isn't going to
| get them adequate comp, maybe politics will.
| zahlman wrote:
| > a company would rather hire 10 "market rate" people
| than 3 well-compensated ones
|
| The former is probably _easier_. They don 't have to
| justify or determine the salaries, and don't have to
| figure out who's worth the money, and don't have to
| figure out _how to figure that out_.
| calenti wrote:
| It also comes that the well-compensated people are
| probably that because they know how to advocate for their
| worth, which usually includes a list of things they will
| tolerate and a list they will not, whereas "market rate"
| is just happy to be there and more inclined to go along
| with, ya know, whatever.
| oarsinsync wrote:
| Alternatively, companies hire multiple subject domain
| experts, and pay them handsomely.
|
| The experts believe they've been hired for the value of
| their opinions, rather than for being 'yes-people', and
| have differing opinions to each other.
|
| At a certain pay threshold, there are multiple peoples
| who's motivation is not "how do I maximise my
| compensation?" and instead is "how do I do the best work
| I can?" Sometimes this presents as vocal disagreements
| between experts.
| jalk wrote:
| There is definitely also a manager dick-measuring contest
| based on headcount, going on in large orgs.
| ngc248 wrote:
| Parkinson's law of organizations clearly explains why
| orgs grow https://en.wikipedia.org/wiki/Parkinson%27s_law
| ngcc_hk wrote:
| I believe incompetence is the key. When someone cannot
| compete (or the office does not use yardstick that can be
| measurable) politics is the only way to get you up.
|
| Switch to what Nobel prize to man instead of the woman
| who do the work ... sometimes. Take the credit and get
| the promotion.
| calenti wrote:
| It's a question of what you want to invest your time in.
| Everyone creates output, whether it's lines of code, a
| smoke screen to hide your social media time, or a set of
| ongoing conversations and perceptions than you have a use
| in the organization.
| eru wrote:
| What industry is that, if I may ask?
| xvector wrote:
| Tech
| dpark wrote:
| Politicking is just group dynamics. In large companies
| people engage in politics because it becomes necessary to
| accomplish large things.
|
| Of course a group can also have bad actors but that's not
| really an issue with politics specifically. Politics are
| neither good nor bad.
| goalieca wrote:
| > In large companies people engage in politics because it
| becomes necessary to accomplish large things.
|
| At a large company, your job after a certain level
| depends on your "impact" and "value delivered". The
| challenge is getting 20 other teams to work on your
| priorities and not their priorities. They too need to
| play to win to keep their job or get that promotion.
| dpark wrote:
| For software engineering, "impact" or "value delivered"
| are pretty much always your job unless you work somewhere
| really dysfunctional that's measuring lines of code or
| some other nonsense. But that does become a lot about
| politics after some level.
|
| I would not say it's about getting other people aligned
| with your priorities instead of theirs but rather finding
| ways such that your priorities are aligned. There's
| always the "your boss says it needs to help me" sort of
| priority alignment but much better is to find shared
| priorities. e.g. "We both need X; let's work together."
| "You need Foo which you could more easily achieve by
| investing your efforts into my platform Bar."
| eru wrote:
| If you are a fresh grad, you can mostly just chug along
| with your tickets and churn out code. Your boss (if you
| have a good boss) will help you make sure the other
| people work with you.
|
| When you are higher up, that is when you become said good
| boss, or that boss's boss, the dynamics of the
| grandfather comment kick in fully.
| dpark wrote:
| Agree. A fresh grad is still measured on "impact" but
| that impact is generally localized. e.g. Quality of
| individual code and design vs ability to wrangle others
| to work with you.
|
| Impact is a handwavy way of saying "is your work good for
| the company".
| quotemstr wrote:
| Politics is just what happens when three or more humans
| get together. It's an inescapable part of human nature.
| tjwebbnorfolk wrote:
| Figuring out how to allocate scarce career resources at a
| company ("impact", recognition, promotions, etc) is
| fundamental to the job of getting stuff done in a large
| organization.
|
| There's an old saying: politics began when two people in
| a cave found themselves with only one blanket.
| another-account wrote:
| Sounds like you're really down on FOSS and think FOSS
| projects don't get stuff done and have no success? You might
| want to think about that a bit more.
| Nextgrid wrote:
| FOSS can _sometimes_ get stuff done but I 'd argue it gets
| stuff done _in spite_ of all the bickering, not because of
| it. If all the energy spent on arguments or "design by
| committee" was spent productively FOSS would go much
| farther (hell maybe we'd finally get that "year of the
| Linux desktop").
| insane_dreamer wrote:
| numpy would like a word
| zahlman wrote:
| I think I understand what you're getting at, but I really
| think "Explicit is better than implicit" here.
| insane_dreamer wrote:
| > This would never work in a FOSS world because the
| project will be stuck in endless planning as everyone
| will have an opinion on how it should be done and nothing
| will actually get done.
|
| numpy is the the de-facto foundation for data science in
| python, which is one of the main reasons, if not the main
| reason, why people use python
|
| it's FOSS
|
| and it "actually got done"
| WD-42 wrote:
| I don't know what you think "typical Foss projects" are but
| in my experience they are exactly like your systemd example:
| one person that does what they want and share it with the
| world. The rest of your argument doesn't really make any
| sense with that in mind.
| Defletter wrote:
| It depends on governance, for want of a better word: if a
| project has a benevolent dictator then that project will
| likely be more productive than one that requires consensus
| building.
| WD-42 wrote:
| That's what I'm saying. Benevolent dictator is the rule,
| not the exception, in FOSS. Which is why GP's argument
| that private companies good, FOSS bad, makes no sense.
| Defletter wrote:
| I think OP is directing their ire towards projects with
| multiple maintainers, thus is more likely to be hamstrung
| by consensus building and is thus less productive. It
| does seem like we've been swamped with drama posts about
| large open-source projects and their governance, notably
| with Rust itself, linux incorporating Rust, Pebble, etc.
| It's not hard to imagine this firehose of dev-drama
| (that's not even about actual code) overshadowing the
| fact that the overwhelming majority of code ever written
| has a benevolent dictator model.
| fragmede wrote:
| The argument isn't about proprietary vs open, but that
| design by committee, whether that committee be a bunch of
| open source heads that we like, or by some group that
| we've been told to other and hate, has limitations that
| have been exhibited here.
| codeflo wrote:
| That's no longer as true as it once was. I get the feeling
| that quite a few people would consider "benevolent dictator
| for life" an outdated model for open source communities.
| For better or worse, there's a lot of push to transition
| popular projects towards being led by committee. Results
| are mixed (literally: I see both successes and failures),
| but that doesn't seem to have any effect on the trend.
| weitendorf wrote:
| Only a very, very small fraction of open source projects
| get to the point where they legitimately need committees
| and working groups and maintainer politics/drama.
|
| > quite a few people would consider "benevolent dictator
| for life" an outdated model for open source communities.
|
| I think what most people dislike are rugpulls and when
| commercial interests override what
| contributors/users/maintainers are trying to get out of a
| project.
|
| For example, we use forgejo at my company because it was
| not clear to us to what extent gitea would play nicely
| with us if we externalized a hosted version/deployment
| their open source software (which they somewhat recently
| formed a company around, and led to forgejo forking it
| under the GPL). I'm also not a fan of what minio did
| recently to that effect, and am skeptical but hopeful
| that seaweedfs is not going to do something similar.
|
| We ourselves are building out a community around our
| static site generator
| https://github.com/accretional/statue as FOSS with
| commercial backing. The difference is that we're open and
| transparent about it from the beginning, and static site
| generators/component libraries are probably some of the
| least painful to fork or take issue with their direction,
| vs critical infrastructure like distributed systems'
| storage layer.
|
| Bottom line is, BDFL works when 1. you aren't asking
| people to bet their business on you staying benevolent 2.
| you remain benevolent.
| Aurornis wrote:
| > Only a very, very small fraction of open source
| projects get to the point where they legitimately need
| committees and working groups and maintainer
| politics/drama.
|
| You're not wrong, but those are the projects we're
| talking about in this thread. uv has become large enough
| to enter this realm.
|
| > Bottom line is, BDFL works when 1. you aren't asking
| people to bet their business on you staying benevolent 2.
| you remain benevolent.
|
| That second point is doing a lot of heavy lifting. All of
| the BDFL models depend on that one person remaining
| aligned, interested, and open to new ideas. A lot of the
| small projects I've worked with have had BDFL models
| where even simple issues like the BDFL becoming busy or
| losing interest became the death knell of the project. On
| the other hand, I can think of a few committee-style
| projects where everything collapsed under infighting and
| drama from the committee.
| quotemstr wrote:
| More projects should push back against calls for
| "governance" and "steering committees" and such. As you
| noticed, they paralyze projects. It took JavaScript seven
| years to get a half-baked version of Python context
| managers, and Python itself has slowed down markedly.
|
| The seemingly irresistible social pressure to committee-
| ize development is a paper tiger. It disappears if you
| stand your ground and state firmly "This is MY project".
| baby wrote:
| That doesn't make any sense. You can do open source by
| yourself and not accept any input.
|
| How's the company behind uv making money?
| Nextgrid wrote:
| > How's the company behind uv making money?
|
| It doesn't have to make money _now_. But it 's clearly
| pouring commercial-project-level of resources into uv, on
| the belief they will somehow recoup that investment later
| on.
| Someone wrote:
| It doesn't hav eto make money _ever_ on us for it to be
| worth it to them.
|
| If you're a Python shop, compare
|
| - writing _uv_ and keeping it private makes package
| management easier for your own packages
|
| - writing _uv_ and opening it up, and getting all /most
| third party libs to use it makes package management
| easier for your own packages and third party packages you
| use
| raincole wrote:
| Is there any sign telling Astral is actually making money via
| uv? How sustainable is it?
|
| I suggest everyone save this comment and review it five years
| later.
| Nextgrid wrote:
| They believe they do or that they will in the future and
| act accordingly.
|
| (whether it will pan out or not is another matter, but in
| the meantime we got a decent open-source package manager
| out of it)
| swores wrote:
| Keep in mind that "making money" doesn't have to be from
| people paying to use uv.
|
| It could be that they calculate the existence of uv saves
| their team more time (and therefore expense) in their other
| work than it used to create. It could be that recognition
| for making the tool is worth the cost as a marketing
| expense. It could be that other companies donate money to
| them either ahead of time in order to get uv made, or after
| it was made to encourage more useful tools to be made. etc
|
| Edit: 6 months ago, user simonw wrote a HN comment _"
| Here's a loose answer to that question from uv founder
| Charlie Marsh last September_ [2024]
| _:https://hachyderm.io/@charliermarsh/113103564055291456
|
| <<<< I don't want to charge people money to use our tools,
| and I don't want to create an incentive structure whereby
| our open source offerings are competing with any commercial
| offerings (which is what you see with a lost of hosted-
| open-source-SaaS business models).
|
| What I want to do is build software that vertically
| integrates with our open source tools, and sell that
| software to companies that are already using Ruff, uv, etc.
| Alternatives to things that companies already pay for
| today.
|
| An example of what this might look like (we may not do
| this, but it's helpful to have a concrete example of the
| strategy) would be something like an enterprise-focused
| private package registry. A lot of big companies use uv. We
| spend time talking to them. They all spend money on private
| package registries, and have issues with them. We could
| build a private registry that integrates well with uv, and
| sell it to those companies. [...]
|
| But the core of what I want to do is this: build great
| tools, hopefully people like them, hopefully they grow,
| hopefully companies adopt them; then sell software to those
| companies that represents the natural next thing they need
| when building with Python. Hopefully we can build something
| better than the alternatives by playing well with our OSS,
| and hopefully we are the natural choice if they're already
| using our OSS. >>>>_
| tonyhart7 wrote:
| "Is there any sign telling Astral is actually making money
| via uv? How sustainable is it?"
|
| maybe they would get acquihire like Bun ???? idk, somebody
| defo needs this
| woile wrote:
| nah, a lot of people working on `uv` have a massive amount of
| experience working on the rust ecosystem, including `cargo`
| the rust package manager. `uv` is even advertised as `cargo`
| for python. And what is `cargo`? a FLOSS project.
|
| Lots of lessons from other FLOSS package managers helped
| `cargo` become great, and then this knowledge helped shape
| `uv`.
| Ar-Curunir wrote:
| IIRC correctly uv was started before Astral (the company
| working on uv)
| raverbashing wrote:
| I 100% agree with this
|
| And it's true, while I disagree with a lot of systemd
| decisions focus has a leveraging effect that's
| disproportional
| tor825gl wrote:
| Why doesn't anaconda disprove this?
| twelvedogs wrote:
| it wouldn't work in a foss world because there's like 5 guys
| doing that shit it in their spare time. that said...
| github...
| panzi wrote:
| Since uv and systemd are both FOSS how are they not part of
| the FOSS world?
| PartiallyTyped wrote:
| You often pay them for their opinions too!
| brap wrote:
| It basically boils down to: capitalism works.
| JasonSage wrote:
| I suspect that the non-Rust improvements are vastly more
| important than you're giving credit for. I think the go version
| would be 5x or 8x compared to the 10x, maybe closer. It's not
| that the Rust parts are insignificant but the algorithmic
| changes eliminate huge bottlenecks.
| eru wrote:
| Though Rust probably helps getting the design right, instead
| of fighting it.
|
| From having sum-types to also having a reasonable packaging
| system itself.
| collinmanderson wrote:
| > the conversation here keeps collapsing back to "Rust rewrite
| good/bad." That feels like cargo-culting the toolchain instead
| of asking the uncomfortable question: why did it take a
| greenfield project to give Python the package manager behavior
| people clearly wanted for the last decade?
|
| I think there's a few things going on here:
|
| - If you're going have a project that's obsessed with speed,
| you might as well use rust/c/c++/zig/etc to develop the
| project, otherwise you're always going to have python and the
| python ecosystem as a speed bottleneck. rust/c/c++/zig
| ecosystems generally care a lot about speed, so you can use a
| library and know that it's probably going to be fast.
|
| - For example, the entire python ecosystem generally does not
| put much emphasis on startup time. I know there's been some
| recent work here on the interpreter itself, but even modules in
| the standard library will pre-compile regular expressions at
| import time, even if they're never used, like the "email"
| module.
|
| - Because the python ecosystem doesn't generally optimize for
| speed (especially startup), the slowdowns end up being
| contagious. If you import a library that doesn't care about
| startup time, why should your library care about startup time?
| The same could maybe be said for memory usage.
|
| - The bootstrapping problem is also mostly solved by using a
| complied language like c/rust/go. If the package manager is
| written in python (or even node/javascript), you first have to
| have python+dependencies installed before you can install
| python and your dependencies. With uv, you copy/install a
| single binary file which can then install python + dependencies
| and automatically do the right thing.
|
| - I think it's possible to write a pretty fast implementation
| using python, but you'd need to "greenfield" it by rewriting
| all of the dependencies yourself so you can optimize startup
| time and bootstrapping.
|
| - Also, as the article mentions there are _some_ improvements
| that have happened in the standards/PEPs that should eventually
| make they're way into pip, though it probably won't be quite
| the gamechanger that uv is.
| zahlman wrote:
| > the entire python ecosystem generally does not put much
| emphasis on startup time.
|
| You'd think PyPy would be more popular, then.
|
| > even modules in the standard library will pre-compile
| regular expressions at import time, even if they're never
| used, like the "email" module.
|
| Hmm, that is slower than I realized (although still just a
| fraction of typical module import time): $
| python -m timeit --setup 'import re' 're.compile("foo.*bar");
| re.purge()' 10000 loops, best of 5: 26.5 usec per loop
| $ python -m timeit --setup 'import sys' 'import re; del
| sys.modules["re"]' 500 loops, best of 5: 428 usec per
| loop
|
| I agree the email module is atrocious in general, which
| specifically matters because it's used by pip for parsing
| "compiled" metadata (PKG-INFO in sdists, when present, and
| METADATA in wheels). The format is intended to look like
| email headers and be parseable that way; but the RFC mandates
| all kinds of things that are irrelevant to package metadata,
| and despite the streaming interface it's hard to actually
| parse only the things you really need to know.
|
| > Because the python ecosystem doesn't generally optimize for
| speed (especially startup), the slowdowns end up being
| contagious. If you import a library that doesn't care about
| startup time, why should your library care about startup
| time? The same could maybe be said for memory usage.
|
| I'm trying to fight this, by raising awareness and by
| choosing my dependencies carefully.
|
| > you first have to have python+dependencies installed before
| you can install python and your dependencies
|
| It's unusual that you actually need to install Python again
| after initially having "python+dependencies installed". And
| pip vendors all its own dependencies except for what's in the
| standard library. (Which is highly relevant to Debian getting
| away with the repackaging that it does.)
|
| > I think it's possible to write a pretty fast implementation
| using python, but you'd need to "greenfield" it by rewriting
| all of the dependencies yourself so you can optimize startup
| time and bootstrapping.
|
| This is my current main project btw. (No, I don't really care
| that uv already exists. I'll have to blog about why.)
|
| > there are _some_ improvements that have happened in the
| standards/PEPs that should eventually make they're way into
| pip
|
| Most of them already have, along with other changes. The 2025
| pip experience is, believe it or not, much better than the
| ~2018 pip experience, notwithstanding higher expectations for
| ecosystem complexity.
| collinmanderson wrote:
| > I agree the email module is atrocious in general
|
| Hah. Yes sounds like we are very much on the same page
| here. Python stdlib could really use a simple generic
| email/http header parser.
|
| > It's unusual that you actually need to install Python
| again after initially having "python+dependencies
| installed".
|
| I'm thinking about 3rd party installers like poetry, pip-
| tools, pdm, etc, where your installer needs
| python+dependencies installed before it can start
| installing.
|
| > "write a pretty fast implementation using python" This is
| my current main project btw. (No, I don't really care that
| uv already exists. I'll have to blog about why.)
|
| Do you have anything public yet? I'm totally curious. I
| started doing this for flake8 and pip back in 2021/2022,
| but when ruff+uv came along I figured it wasn't worth my
| time any more.
| zahlman wrote:
| > Do you have anything public yet?
|
| The repo is https://github.com/zahlman/paper but it's not
| really usable and it's missing a bunch of local very
| unfinished stuff (and my README template definitely needs
| fixing). More of a "watch this space" but I would really
| like to push out a Show HN for the first chunk of
| functionality soon.
| optionalsquid wrote:
| > You'd think PyPy would be more popular, then.
|
| PyPy is hamstrung by a limited (previously, a lack of)
| compatibility with compiled Python modules. If it had been
| a drop-in replacement for the equivalent Python versions,
| then it'd probably have been much more popular
| CamouflagedKiwi wrote:
| > You'd think PyPy would be more popular, then.
|
| PyPy doesn't do anything to help startup time. In fact,
| it's typically a bit slower to start up than CPython.
|
| You reap the speed benefits from PyPy once it's been
| running for a little while and it can JIT compile the hot
| bits of code.
| zahlman wrote:
| > PyPy doesn't do anything to help startup time. In fact,
| it's typically a bit slower to start up than CPython.
|
| Considerably slower on my machine. Yes, that was my
| point. If the community doesn't care about startup time,
| you'd expect more adoption of an implementation that
| sacrifices that startup time for later performance.
| eru wrote:
| > That feels like cargo-culting the toolchain [...]
|
| Pun intended?
|
| Jokes aside, what you describe is a common pattern. It's also
| why Google internally they used to get decent speedups from
| rewriting some old C++ project in Go for a while: the magic was
| mostly in the rewrite-with-hindsight.
|
| If you put effort into it, you can also get there via an
| incremental refactoring of an existing system. But the rewrite
| is probably easier to find motivation for, I guess.
| benreesman wrote:
| I have been a big Astral and uv booster for a long time. But
| specifications like this one:
| https://gist.github.com/b7r6/47fea3c139e901cd512e15f42355f26...
| have me re-evaluating everything.
|
| That's TensorRT-LLM in it's entirety at 1.2.0rc6 locked to run
| on Ubuntu or NixOS with full MPI and `nvshmem`, the DGX
| container Jensen's Desk edition (I know because I also rip
| apart and `autopatchelf` NGC containers for repackaging on
| Grace/SBSA).
|
| It's... arduous. And the benefit is what exactly? A very mixed
| collection of maintainers have asserted that software behavior
| is monotonic along a single axis most of which they can't see
| and we ran a solver over those guesses?
|
| I think the future is collections of wheels that have been
| through a process the consumer regards as credible.
| jeeeb wrote:
| > That feels like cargo-culting the toolchain instead of asking
| the uncomfortable question: why did it take a greenfield
| project to give Python the package manager behavior people
| clearly wanted for the last decade?
|
| This feels like a very unfair take to me. Uv didn't happen in
| isolation, and wasn't the first alternative to pip. It's built
| on a lot of hard work by the community to put the standards in
| place, through the PEP process, that make it possible.
|
| What uv did was to bring it all together.
| moab wrote:
| The point stands that it's less about the language than doing
| said hard work in any reasonable programming language.
| ChadNauseam wrote:
| I don't know the problem space and I'm sure that the language-
| agnostic algorithmic improvements are massive. But to me,
| there's just something about rust that promotes fast code. It's
| easy to avoid copies and pointer-chasing, for example. In
| python, you never have any idea when you're copying, when
| you're chasing a pointer, when you're allocating, and so on.
| (Or maybe you do, but I certainly don't.) You're so far from
| hardware that you start thinking more abstractly and not
| worrying about performance. For some things, that's probably
| perfect. But for writing fast code, it's not the right mindset.
| zahlman wrote:
| The thing is that a lot of the bottlenecks in pip are
| entirely artificial, and a lot of the rest can't really be
| improved by rewriting in Rust _per se_ , because they're
| _already_ written in C (within the Python interpreter
| itself).
| firesteelrain wrote:
| Uv is great but seems still everyone is cargo culting Rust.
| We still have Poetry and PDM.
| zahlman wrote:
| > it's how much speed we "unlocked" just by finally treating
| Python packaging as a well-specified systems problem instead of
| a pile of historical accidents.
|
| A lot of that, in turn, boils down to _realizing_ that it
| _could be_ fast, and then _expecting_ that and _caring_ enough
| about it.
|
| > but with the same design decisions (PEP 517/518/621/658
| focus, HTTP range tricks, aggressive wheel-first strategy,
| ignoring obviously defensive upper bounds, etc.), I strongly
| suspect we'd be debating a 1.3x vs 1.5x speedup instead of a
| 10x headline
|
| I'm doing a project of this sort (although I'm hoping not to
| reinvent the wheel (heh) for the actual resolution algorithm).
| I fully expect that some things will be barely improved or even
| slower, but many things will be nearly as fast as with uv.
|
| For example, installing from cache (the focus for the first
| round) mainly relies on tools in the standard library that are
| written in C and have to make system calls and interact with
| the filesystem; Rust can't do a whole lot to improve on that.
| On the other hand, a new project can improve by storing
| unpacked files in the cache (like uv) instead of just the
| artifact (I'm storing both; pip stores the artifact, but with a
| msgpack header) and hard-linking them instead of copying them
| (so that the system calls do less I/O). It can also improve by
| actually making the cached data accessible without a network
| call (pip's cache is an HTTP cache; contacting PyPI tells it
| what the original download URL is for the file it downloaded,
| which is then hashed to determine its path).
|
| For another example, pre-compiling bytecode can be
| parallelized; there's even already code in the standard library
| for it. Pip hasn't been taking advantage of that all this time,
| but to my understanding it will soon feature its own logic
| (like uv does) to assign files to compile to worker processes.
| But Rust can't really help with the actual logic being
| parallelized, because that, too, is written purely in C (at
| least for CPython), within the interpreter.
|
| > why did it take a greenfield project to give Python the
| package manager behavior people clearly wanted for the last
| decade?
|
| (Zeroth, pip _has been doing_ HTTP range tricks, or at least
| trying, for quite a while. And the exact point of PEP 658 is to
| obsolete them. It just doesn 't really work for sdists with the
| current level of metadata expressive power, as in other PEPs
| like 440 and 508. Which is why we have more PEPs in the
| pipeline trying to fix that, like 725. And discussions and
| summaries like https://pypackaging-native.github.io/.)
|
| First, you have to write the standards. People in the community
| expect interoperability. PEP 518 exists specifically so that
| people could start working on alternatives to Setuptools as a
| build backend, and PEP 517 exists so that such alternatives
| could have the option of providing _just_ the build backend
| functionality. (But the people making things like Poetry and
| Hatch had grander ideas anyway.)
|
| But also, _consider the alternative_ : the only other viable
| way would have been for pip to totally rip apart established
| code paths and possibly break compatibility. And, well, if you
| used and talked about Python at any point between 2006 and
| 2020, you should have the first-hand experience required to
| complete that thought.
|
| Specifically regarding the "aggressive wheel-first strategy", I
| strongly encourage you to read the discussion on
| https://github.com/pypa/pip/issues/9140.
| iamaredpanda wrote:
| Poetry largely accomplished the same thing first with most of
| the speedups (except managing your python installations) and
| had the disadvantage of starting before the PEPs you mentioned
| were standardized.
| lmm wrote:
| Note that the advantages of Rust are not just execution speed:
| it's also a good language for expressing one's thoughts, and
| thus makes it easier to find and unlock the algorithmic
| speedups that really increase speed.
|
| But yeah. Python packaging has been dumb for decades and
| successive Python package managers recapitulated the same
| idiocies over and over. Anyone who had used both Python and a
| serious programming language knew it, the problem was getting
| anyone to do anything about it. I can't help thinking that
| maybe the main reason using Rust worked is that it forced
| anyone who wanted to contribute to it to experience what using
| a language with a non-awful package manager is like.
| formerly_proven wrote:
| Cargo is not really good. The very much non-zero frequency of
| something with cargo not working for opaque reasons and then
| suddenly working again after "cargo clean", the "no, _I_
| invoke your binaries "-mentality (try running a benchmark
| without either ^C'ing out of bench to copy the binary name or
| parsing some internal JSON metadata) because _" cargo build"
| is the only build system in the world which will never tell
| you what it built_, the whole mess with features, default-
| features, no-default-features, of course bindgen/sys
| dependency conflicts, "I'll just use the wrong -L libpath for
| the bin crate but if I'm building tests I remember the
| ...64". cargo randomly deciding that it now has to rebuild
| everything or 50% of everything for reasons which are never
| to be known, builds being not reproducible, cargo just never
| cleaning garbage up and so on.
|
| rustdoc has only slightly changed since the 2010s, it's still
| very hard to figure out generic/trait-oriented APIs, and it
| still only does API documentation in mostly the same basic
| 1:1 "list of items" style. Most projects end up with two
| totally disjointed sets of documentation, usually one
| somewhere on github pages and the rustdoc.
|
| Rust is overall good language, don't get me wrong. But it and
| the ecosystem also has a ton of issues (and that's without
| even mentioning async), and most of these have been sticking
| around since basically 1.0.
|
| (However, the rules around initialization are just stupid and
| unsafe is no good. Rust also tends to favor a very
| allocation-heavy style of writing code, because avoiding
| allocations tends to be possible but often annoying and
| difficult in unique-to-rust ways. For somewhat related
| reasons, trivial things are at times really hard in Rust for
| no discernible reason. As a concrete, simplistic but also
| real-world example, Vec::push is an _incredibly pessimistic_
| method, but if you want to get around it, you either have to
| initialize the whole Vec, which is a complete waste of
| cycles, or you yolo it with reserve+set_len, which is invalid
| Rust because you didn 't properly use MaybeUninit for
| locations which are only ever written.)
| mlrtime wrote:
| I have empathy for anyone who was required to use cargo on
| a nfs mounted fs. The number of files and random IO cargo
| uses makes any large project unusable.
|
| I had to stop telling people to stop syncing their cargo
| env around nfs so many times, but sometimes they have no
| choice.
| metaltyphoon wrote:
| > nfs mounted fs
|
| Anything doing locks on nfs, including trying to use
| sqlite, is a mistake. This is not a cargo problem this is
| a nsf problem.
| burntsushi wrote:
| > or you yolo it with reserve+set_len, which is invalid
| Rust because you didn't properly use MaybeUninit for
| locations which are only ever written
|
| `Vec::spare_capacity_mut`[1] gives you a view into the
| unused capacity. There's nothing "invalid" about it.
|
| [1]: https://doc.rust-
| lang.org/std/vec/struct.Vec.html#method.spa...
| kibwen wrote:
| Cargo is fantastic... for building Rust code. Once you
| start trying to also use it to build C code, you're moving
| outside of Cargo's wheelhouse, using features that Cargo
| only supports begrudgingly (like build scripts). Cargo is
| definitely not intended to be an end-all be-all build
| system for all languages; it's specialized for Rust, and
| that's what it's great at. For multi-language projects, you
| want some sort of simple tool to orchestrate the builds
| (e.g. `just` https://just.systems/man/en/ ) that internally
| calls out to Cargo (and whatever other build systems you
| have for whatever other languages you're using). The
| overall mistake is thinking that Cargo is a replacement for
| `make`, when it isn't nearly so general.
| aragilar wrote:
| Because it broke backwards compatibility? It's worth noting
| that setuptools is in a similar situation to pip, where any
| change has a high chance of breaking things (as can be seen by
| perusing the setuptools and pip bug trackers). PEP 517/518
| removed the implementation-defined nature of the ecosystem
| (which had caused issues for at least a decade, see e.g. the
| failures of distutils2 and bento), instead replacing it with a
| system where users complain about which backend to use (which
| is at least an improvement on the previous situation)...
| andai wrote:
| It just has to do with values. If you value perf you aren't
| going to write it in Python. And if you value perf then
| everything else becomes a no brainer as well.
|
| It's the same way in JS land. You can make a game in a few
| kilobytes, but most web pages are still many megabytes for what
| should have been no JS at all.
| jbs789 wrote:
| "Why did it take a greenfield project...?"
|
| By definition greenfield projects literally means free from
| constraints.
|
| So the answer is in your question: Why did it take a team
| unbound by constraints to try something new, as compared to a
| project with millions of existing stakeholders?
|
| Single vision. Smaller team. What they landed on is a hit (no
| guarantee of that in advance!)
|
| Conversely, with so many stakeholders, getting everyone to
| rally around a change (in advance) is hard.
|
| In my experience this is about human nature/organisation and
| spans all types of organisations, not just python or open
| source etc.
|
| It also looks like python would have got there, given the
| foundations put in place as noted in the article.
| dangoodmanUT wrote:
| > Zero-copy deserialization
|
| Just a nit on this section: zero-copy deserialization is not Rust
| specific (see flatbuffers). rkyv as a crate for doing so in Rust
| is though
| est wrote:
| > Virtual environments required
|
| This bothers me more than once when building a base docker image.
| Why would I want a venv inside a docker with root?
| forrestthewoods wrote:
| Because a single docker image can run multiple programs that
| have mutually exclusive dependencies?
|
| Personally I never want program to ever touch global shared
| libraries ever. Yuck.
| est wrote:
| > a single docker image can run multiple programs
|
| You absolutely can. But it's not best practice.
|
| https://docs.docker.com/engine/containers/multi-
| service_cont...
| forrestthewoods wrote:
| God I hate docker so much. Running computers does not have
| to be so bloody complicated.
| pornel wrote:
| The old package managers messing up the global state by default
| is the reason why Docker exists. It's the venv for C.
| shevy-java wrote:
| Soon uv will deliver results without you even thinking about them
| beforehand!
| PrettyPastry wrote:
| I wish this were enough to get the flake8 devs to accept
| pyproject support PRs.
| dxdm wrote:
| Stop using flake8 and use ruff instead. It's made by the same
| folks that make uv.
| dmarwicke wrote:
| wait, zero-copy deserialization isn't rust-specific. you can mmap
| structs in C. done it before, works fine
| zahlman wrote:
| The point is that it would be difficult in Python, compared to
| in "system" compiled languages generally.
| rao-v wrote:
| I have to say it's just lovely seeing such a nicely crafted and
| written technical essay. It's so obvious that this is crafted by
| hand, and reading it just reemphasises how much we've lost
| because technical bloggers are too ready to hand the keys over to
| LLMs.
| yakshaving_jgt wrote:
| This post was very clearly written with an LLM.
| annexrichmond wrote:
| > This reduces resolver backtracking dramatically since upper
| bounds are almost always wrong.
|
| I am surprised by this because Python minor versions break
| backwards compatibility all the time. Our company for example is
| doing a painful upgrade from py39 to py311
| zahlman wrote:
| Could you explain what major pain points you've encountered? I
| can't think of any common breakages cited in 3.10 or 3.11
| offhand. 3.12 had a lot more standard library removals, and the
| `match` statement introduced in 3.10 uses a soft keyword and
| won't break code that uses `match` as an identifier.
| pjjpo wrote:
| > npm's package.json is declarative
|
| lol
| Revisional_Sin wrote:
| > Ignoring requires-python upper bounds. When a package says it
| requires python<4.0, uv ignores the upper bound and only checks
| the lower. This reduces resolver backtracking dramatically since
| upper bounds are almost always wrong. Packages declare python<4.0
| because they haven't tested on Python 4, not because they'll
| actually break. The constraint is defensive, not predictive.
|
| Erm, isn't this a bit bad?
| Pawamoy wrote:
| No. When such upper bounds are respected, they contaminate
| other packages, because you have to add them yourself to be
| compatible with your dependencies. Then your dependents must
| add them too, etc. This brings only pain. Python 4 is not even
| a thing, core developers say there won't ever be a Python 4.h
| akoboldfrying wrote:
| > you have to add them yourself to be compatible with your
| dependencies
|
| This is no more true for version upper bounds than it is for
| version lower bounds, assuming that package installers ensure
| all package version constraints are satisfied.
|
| I presume you think version lower bounds should still be
| honoured?
| zahlman wrote:
| The point is that you can _know_ that a lower bound is
| necessary at the time of publication; an upper bound is
| either speculative or purely defensive, and has possibly
| unnecessary consequences for your dependents.
| aragilar wrote:
| Yes, but it's (probably) the least worse thing they can do
| given how the "PyPI" ecosystem behaves. As PyPI does not allow
| replacement of artefacts (sdists, wheels, and older formats),
| and because there is no way to update/correct metadata for the
| artefacts, unless the uploader knew at upload time of
| incompatibilities between their package and and the upper-
| bounded reference (whether that is the Python interpreter or a
| Python package), the upper bound does not reflect a known
| incompatibility. In addition, certain tools (e.g. poetry) added
| the upper bounds automatically, increasing the amount of
| spurious bounds. https://iscinumpy.dev/post/bound-version-
| constraints/ provides more details.
|
| The general lesson from this is when you do not allow
| changes/replacement of invalid data (which is a legitimate
| thing to do), then you get stuck with handling the bad data in
| every system which uses it (and then you need to worry about
| different components handling the badness in different ways,
| see e.g. browsers).
| almosthere wrote:
| Our next trick, getting people to stop writing code (so we can
| stop writing python)
| TrayKnots wrote:
| I usually don't see the importance of speed in one-time costs...
| But hey, same discussion with npm, yarn, pnpm...
| vjay15 wrote:
| Amazing that how much python's pip was so bottlenecked, it was
| basic design problem damn
| sghaz wrote:
| Liked the focus on standards and ecosystem decisions rather than
| just "it's fast because Rust."
|
| One small timeline nit: the article mentions PEP 517 as being
| from 2017, but the PEP itself was created in 2015. From the PEP
| header:
|
| Created: 30-Sep-2015 [1]
|
| It did see important revisions and wider adoption around 2017, so
| I assume that's what was meant.
|
| [1] https://peps.python.org/pep-0517/
| pritambarhate wrote:
| Does anyone know how does Astral.sh plan to make money?
| zahlman wrote:
| Via services like https://astral.sh/pyx , IIRC.
| trashburger wrote:
| > Ignoring requires-python upper bounds. When a package says it
| requires python<4.0, uv ignores the upper bound and only checks
| the lower. This reduces resolver backtracking dramatically since
| upper bounds are almost always wrong. Packages declare python<4.0
| because they haven't tested on Python 4, not because they'll
| actually break. The constraint is defensive, not predictive.
|
| This is clearly LLM-generated and the other bullet points have
| the same smell. Please use your own words.
| quantbagel wrote:
| When I made a swift package manager as Rust rewrite I realized
| that the language wasn't the issue, design is a lot more
| important. Rust just gave a boost to everything else. you can try
| Gust here https://github.com/quantbagel/gust a lot better than
| using SwiftPM but there's room for improvement! Make issues with
| your ideas
| ldng wrote:
| That might be how uv got fast but that is _not_ why it got
| popular.
|
| PyPA has been a mess for a very long time for in-fighting,
| astroturfing, gatekeeping and so on with pip being the
| battlefield. The uv team just did one thing that PyPA & co
| stopped doing a long time ago (if they ever did ...) : actually
| solving pain point of their user and never saying "it's not
| possible because [insert bullshit]" or reply "it's OSS, do it
| yourself" to then reject the work with attitude and baseless
| argument.
|
| They listened to their user's issues and solved their pain points
| without denying them. period.
| markkitti wrote:
| Summary: They fixed Python packaging by not having to run Python
| to resolve dependencies. Also, they used Rust.
|
| Moral of the story: Use less Python. Use declarative
| configuration and other langauges instead.
___________________________________________________________________
(page generated 2025-12-27 23:01 UTC)