Just a few months back I said I would never use uv. I was already used to venv and pip. No need for another tool I thought.
I now use uv for everything Python. The reason for the switch was a shared server where I did not have root and there were all sorts of broken packages/drivers and I needed pytorch. Nothing was working and pip was taking ages. Each user had 10GB of storage allocated and pip's cache was taking up a ton of space & not letting me change the location properly. Switched to uv and everything just worked
If you're still holding out, really just spend 5 minutes trying it out, you won't regret it.
For me, the big key was: uv is so much easier to explain and especially use - especially for people who sometimes script something in python and don't do this daily.
pip + config file + venv requires you to remember ~2 steps to get the right venv - create one and install stuff into it, and for each test run, script execution and such, you need to remember a weird shebang-format, or to activate the venv. And the error messages don't help. I don't think they could help, as this setup is not standardized or blessed. You just have to beat a connection of "Import Errors" to venvs into your brain.
It's workable, but teaching this to people unfamiliar with it has reminded me how.. squirrely the whole tooling can be, for a better word.
Now, team members need to remember "uv run", "uv add" and "uv sync". It makes the whole thing so much easier and less intimidating to them.
Unfortunately uWSGI (one of the most important libraries) is fundamentally incompatible with uv. had to roll back all my apps that use custom uWSGI for that reason.
Similarly to the sibling I also use both. I let mise manage my uv version (and other tools) and let uv handle Python + PyPI Packages for me. Works great!
Think of uv more as like npm or other thing like that. The new Python pyproject.toml is similar package.json. It defines the project description, list of dependencies, and other hooks. Uv is a package/project tool using pyproject.toml. It is easy to manage dependencies, build and publish to PyPi, add hooks to run tests, linters, or whatever, again much like package.json. It also manages the virtualenv automatically, though you can manage it yourself.
Thanks for mentioning mise. I'm more interested in it for the task running feature. I couldn't figure out how to have shell scripts in Justfile, so I gave up on it.
What has been holding me back on uv is my experience with Ruff. Ruff claims "Drop-in parity with Flake8, isort, and Black", but that is simply not true. At least for isort, Ruff only re-implemented what they wanted and then ask you to use Ruff to call out to the old isort tool if there's a feature or setting that's missing in the Ruff re-implementation. So what's the point? Ruff just partially re-implemented many existing different tools and added some new ones. So using Ruff actually increases the amount of tools, yet again, you're having to use because of this and it also not doing everything that Pylint does.
For moving to uv, I haven't heard a good story for what uv provides over Poetry rather than "is fast". The only unique thing that I am currently aware of is that uv can install Python itself, which gets rid of tools like Pyenv. I'm interested because of that, but "is fast" isn't enough of a reason.
My experience is that ruff reimplemented 99% of the most popular features of black, isort, flake8, pylint, etc. and then added 10000% more features on top, that feels like a fair tradeoff to me.
I've converted multiple large Python codebases to ruff, and each time I just configure ruff as close to the previous tools as possible, then reformat the entire codebase with ruff and remove all the previous tools. The speed increase when linting alone is worth the minor formatting changes to me.
If you really insist on keeping isort's sorting then you could at least replace black and pylint, which would reduce the total number of tools by one.
I think you're underestimating how "fast" uv really is. It's night and day different. The sentence that got me to switch and I echo still was: "uv is so fast, I sometimes don't even think it's actually doing anything". The first time I used it, I had to actually double check if uv actually was working and installing the packages that it was saying it was. There's a lot of reasons I've heard not to use it that kind of (not really) make sense (you don't want another package manager, you're happy with just base pip, etc). But if you're already using poetry, you really should just switch. uv is just poetry but without any waiting.
Even your most complicated projects should be able to switch within a day. The only reason I took any time was having to restructure my docker containers to work with uv instead of poetry. And that's mostly with my inexperience with docker, not because uv is complicated.
> Each user had 10GB of storage allocated and pip's cache was taking up a ton of space & not letting me change the location properly. Switched to uv and everything just worked
Is it better about storage use? (And if so, how? Is it just good at sharing what can be shared?)
similar story recently with an experimental repo that starts with "its so easy, just $uv a b c" .. under the hood it implies a lot of redundancies? but true enough it worked fine and trouble-free too, on a standard GNU-Debian-Ubuntu host
> Just a few months back I said I would never use uv. I was already used to venv and pip. No need for another tool I thought
Really? :)
requirements.txt is just hell and torture. If you've ever used modern project/dependency management tools like uv, Poetry, PDM, you'll never go back to pip+requirements.txt. It's crazy and a mess.
uv is super fast and a great tool, but still has roughnesses and bugs.
Pip-tools+requirements.txt helped me survive the past few years. I also never thought I needed uv, but after all the talk about it I gave it a spin and never want back. It’s just so blazing fast en convenient.
I remember using pip and venv back in like 2009. Last time I checked, maybe 5 or 10 years ago, the recommendation of the community was generally to just use Docker instead of all these tools. Did that not catch on?
The advice seems to change every year. For a while it was venv, then pipenv, poetry, docker, and now uv. Maybe the ecosystem will settle on that but who knows.
Docker was always a workaround to Python not having a non-awful dependency manager. uv is that non-awful dependency manager, and I expect in the long term it will reduce the use of Docker.
Docker solves a different problem. Docker is a way to basically ship your whole OS off to another machine. You still have to have a way to install the right version of python and all the python libraries you need inside the Docker container, and uv is great for this.
Secondly Docker only solves a subset of problems. It's fine if you're developing a server that you will be deploying somewhere. It's inconvenient if you're developing an end user application, and it's completely useless if you're developing a library you want people to be able to install.
I love uv. The one gotcha I'll warn people about is: don't touch uvx. I've lost an embarrassing number of hours or days trying to figure out why nothing works properly or makes sense when I tried to run things with uvx. I guess I understand why it's there, but I think it's a built-in foot-gun and not well documented. But if you stay away from it, things work great.
The first time I used `uv`, I was sure that I had made a mistake or typed something wrong because the process finished so much more quickly than anything I had ever experienced with `pip`.
uv and ruff are a great counterexample to all those people who say "never reinvent the wheel". Don't ever do it just for the sake of doing it, but if you have focused goals you can sometimes produce a product that's an order of magnitude better.
I believe most of the time this phrase is said to an inexperienced artisan who has no idea how the current system works, what's the shortcoming of it, and how to improve upon it. Think of an undergraduate student who tries to solve the Goldbach conjecture. Usually what ended up is either he fails to reinvent the wheel, or reinvent the exact same wheel, which has no value. The phrase certainly does not apply to professionals.
Even then, you know what's a good way to learn about how the current system works etc, maybe even the best way? I've got many failed projects behind me, and 0 regrets.
A big part of the "magic" is that there is a team of paid professionals maintaining and improving it. That's more important than it being written in Rust. If uv were forked it would devolve to the level of pip over time.
I'd be curious to know exactly what changed. Python -> Rust won't make network downloads faster nor file I/O faster. My naive guess is that all the speed comes from choosing better algorithms and/or parallelizing things. Not from Python vs Rust (though if it's hard to parallelize in Python and easy in rust that would certainly make a difference)
Python package management was notoriously awful. The problem wasn't that people were trying to do things better, it was that they weren't; every new Python dependency management tool just repeated the mistakes of all the previous Python dependency management tools. uv is the first one to break the cycle (and it's probably not a coincidence that it's the first one to not be written in Python).
Honestly "don't reinvent the wheel" makes absolutely no sense as a saying. We're not still all using wooden discs as wheels, we have invented much better wheels since the neolithic. Why shouldn't we do the same with software?
Right, wheels are reinvented every few years. Compare tires of today to the ones 20 years ago and the technology and capability is very different, even though they look identical to a casual eye.
My primary vehicle has off-road capable tires that offer as much grip as a road-only tire would have 20-25 years ago, thanks to technology allowing Michelin to reinvent what a dual-purpose tire can be!
I always took this saying as meaning that we don’t re-invent the concept of the wheel. For example the Boring company and Tesla hoping to reinvent the concept of the bus/train.. (iirc your car goes underground on some tracks and you get to bypass traffic and not worry about steering)
A metal wheel is still just a wheel. A faster package manager is still just a package manager.
I also like Dan Luu's take (starting with a Joel Spolsky quote)
“Find the dependencies — and eliminate them.” When you're working on a really, really good team with great programmers, everybody else's code, frankly, is bug-infested garbage, and nobody else knows how to ship on time.
We had a similar attitude, although I'd say that we were a bit more humble. We didn't think that everyone else was producing garbage but, we also didn't assume that we couldn't produce something comparable to what we could buy for a tenth of the cost. From talking to folks at some competitors, there was a pretty big cultural difference between how we operated and how they operated. It simply didn't occur to them that they didn't have to buy into the standard American business logic that you should focus on your core competencies, that you can think through whether or not it makes sense to do something in-house on the merits of the particular thing instead of outsourcing your thinking to a pithy saying.[0]
I came here to (wrongly) say that wooden disks were never used as wheels, and that ot all started with spokes.
Some checking showed that, in fact, the oldest known wheels have a lot of solid disks. E.g: https://en.m.wikipedia.org/wiki/Ljubljana_Marshes_Wheel
Hopefully this can disabuse others of similar mistaken memory.
It's meant to signify a step change.
Order of magnitude change = no amount of incremental changes would make up for it.
In common conversation, the multiplier can vary from 2x - 10x. In context of some algorithms, order of magnitudes can be over the delta rather than absolutes. eg: an algorithms sees 1.1x improvement over the previous 10 years. A change that shows a 1.1x improvement by itself, overshadows an an order-of-magnitude more effort.
For salaries, I've used order-of-magnitude to mean 2x. Good way to show a step change in a person's perceived value in the market.
"10x" has been cheapened / heard enough / de facto, is a more general statement than a literal interpretation would indicate. (i.e. 10x engineer. Don't hear that much around these parts these days)
Order of magnitude faces less of that baggage, until it does :)
Just a warning in case others run into it: on very anemic systems (e.g.: AWS T2.micro running Windows, yes... I know...) uv will try to open too many simultaneous downloads, overloading things, resulting in timeouts.
You can use ent ENV variable UV_CONCURRENT_DOWNLOADS to limit this. In my case it needed to be 1 or 2. Anything else would cause timeouts.
An extreme case, I know, but I think that uv is too aggressive here (a download thread for every module). And should use aggregate speeds from each source server as a way of auto-tuning per-server threading.
Not extreme at all, A lot of people use the cheapest smallest VPS for their hobby work. I know I do (albeit not AWS). Thanks for sharing, hope they improve the automatic detection there.
uv can also run even a beefy linux desktop out of file descriptors for larger projects. And does not have deterministic / reproducible installs. Still needs maturity.
I built a Claude Project with special instructions just teaching it how to do this, which means it can output full scripts for me with inline dependencies based on a single prompt: https://simonwillison.net/2024/Dec/19/one-shot-python-tools/
Claude 4's training cutoff date is March 2025 though, I just checked and it turns out Claude Sonnet 4 can do this without needing any extra instructions:
Python script using uv and inline script dependecies
where I can give it a URL and it scrapes it with httpx
and beautifulsoup and returns a CSV of all links on
the page - their URLs and their link text
Using your system instructions for uv for every LLM now since first seeing your post last year, thanks! It's insanely helpful just asking e.g. Claude to give me a python script for XYZ and just using "uv run". I also added:
If you need to run these scripts, use "uv run script-name.py". It will automatically install the dependencies. Stdlibs don't need to be specified in the dependencies array.
since e.g. Cursor often gets confued because the dependencies are not installed and it doesn't know how to start the script. The last sentence is for when LLMs get confused and want to add "json" for example to the dependency array.
claude sonnet typically forgets about uv script syntax in my experience. I usually find myself having to paste in the docs every time. By default it wants to use uv project syntax.
Started using this recently for personal stuff on my laptop. When you're used to pip, it's just confusingly fast. More than once I thought maybe it didn't work because it returned too quickly..
Tried uv a while ago and I was shocked by how fast and easy it is to use. There's basically no reason to use pip anymore, and if you're using only Python there's basically no reason to use conda either.
Until the moment you will realize that ruff perform only a part of pylint checks and that very obvious mistakes can go through easily like code that can't run because of an obvious error.
I now use uv for everything Python. The reason for the switch was a shared server where I did not have root and there were all sorts of broken packages/drivers and I needed pytorch. Nothing was working and pip was taking ages. Each user had 10GB of storage allocated and pip's cache was taking up a ton of space & not letting me change the location properly. Switched to uv and everything just worked
If you're still holding out, really just spend 5 minutes trying it out, you won't regret it.
pip + config file + venv requires you to remember ~2 steps to get the right venv - create one and install stuff into it, and for each test run, script execution and such, you need to remember a weird shebang-format, or to activate the venv. And the error messages don't help. I don't think they could help, as this setup is not standardized or blessed. You just have to beat a connection of "Import Errors" to venvs into your brain.
It's workable, but teaching this to people unfamiliar with it has reminded me how.. squirrely the whole tooling can be, for a better word.
Now, team members need to remember "uv run", "uv add" and "uv sync". It makes the whole thing so much easier and less intimidating to them.
Deleted Comment
There's also some additional integration which I haven't tried yet: https://mise.jdx.dev/mise-cookbook/python.html#mise-uv
For moving to uv, I haven't heard a good story for what uv provides over Poetry rather than "is fast". The only unique thing that I am currently aware of is that uv can install Python itself, which gets rid of tools like Pyenv. I'm interested because of that, but "is fast" isn't enough of a reason.
I've converted multiple large Python codebases to ruff, and each time I just configure ruff as close to the previous tools as possible, then reformat the entire codebase with ruff and remove all the previous tools. The speed increase when linting alone is worth the minor formatting changes to me.
If you really insist on keeping isort's sorting then you could at least replace black and pylint, which would reduce the total number of tools by one.
Even your most complicated projects should be able to switch within a day. The only reason I took any time was having to restructure my docker containers to work with uv instead of poetry. And that's mostly with my inexperience with docker, not because uv is complicated.
Is it better about storage use? (And if so, how? Is it just good at sharing what can be shared?)
Really? :)
requirements.txt is just hell and torture. If you've ever used modern project/dependency management tools like uv, Poetry, PDM, you'll never go back to pip+requirements.txt. It's crazy and a mess.
uv is super fast and a great tool, but still has roughnesses and bugs.
Dead Comment
Secondly Docker only solves a subset of problems. It's fine if you're developing a server that you will be deploying somewhere. It's inconvenient if you're developing an end user application, and it's completely useless if you're developing a library you want people to be able to install.
[1] https://docs.astral.sh/uv/guides/tools/#commands-with-plugin...
You don't have that problem with Poetry. You go make a cup of coffee for a couple minutes, and it's usually done when you come back.
The improvements came from lots of work from the entire python build system ecosystem and consensus building.
The good thing about reinventing the wheel is that you can get a round one.
https://scripting.wordpress.com/2006/12/20/scripting-news-fo...
My primary vehicle has off-road capable tires that offer as much grip as a road-only tire would have 20-25 years ago, thanks to technology allowing Michelin to reinvent what a dual-purpose tire can be!
A metal wheel is still just a wheel. A faster package manager is still just a package manager.
“Find the dependencies — and eliminate them.” When you're working on a really, really good team with great programmers, everybody else's code, frankly, is bug-infested garbage, and nobody else knows how to ship on time.
We had a similar attitude, although I'd say that we were a bit more humble. We didn't think that everyone else was producing garbage but, we also didn't assume that we couldn't produce something comparable to what we could buy for a tenth of the cost. From talking to folks at some competitors, there was a pretty big cultural difference between how we operated and how they operated. It simply didn't occur to them that they didn't have to buy into the standard American business logic that you should focus on your core competencies, that you can think through whether or not it makes sense to do something in-house on the merits of the particular thing instead of outsourcing your thinking to a pithy saying.[0]
[0] https://danluu.com/nothing-works/
Hopefully this can disabuse others of similar mistaken memory.
off topic, but i wonder why that phrase gets used rather than 10x which is much shorter.
Long answer: Because if you put a number, people expect it to be accurate. If it was 6x faster, and you said 10x, people may call you out on it.
In common conversation, the multiplier can vary from 2x - 10x. In context of some algorithms, order of magnitudes can be over the delta rather than absolutes. eg: an algorithms sees 1.1x improvement over the previous 10 years. A change that shows a 1.1x improvement by itself, overshadows an an order-of-magnitude more effort.
For salaries, I've used order-of-magnitude to mean 2x. Good way to show a step change in a person's perceived value in the market.
Order of magnitude faces less of that baggage, until it does :)
- 10x is a meme
- what if it's 12x better
You can use ent ENV variable UV_CONCURRENT_DOWNLOADS to limit this. In my case it needed to be 1 or 2. Anything else would cause timeouts.
An extreme case, I know, but I think that uv is too aggressive here (a download thread for every module). And should use aggregate speeds from each source server as a way of auto-tuning per-server threading.
Claude 4's training cutoff date is March 2025 though, I just checked and it turns out Claude Sonnet 4 can do this without needing any extra instructions:
Here's the output, it did the right thing with regards to those dependencies: https://claude.ai/share/57d5c886-d5d3-4a9b-901f-27a3667a8581https://github.com/shakefu/cursor-rules/blob/f4dffbbf04ce99f...
Instant reactive reproducible app that can be sent to others with minimal prerequisites (only uv needs to be installed).
Such a hot combo.
- https://everything.intellectronica.net/p/the-little-scripter
- https://www.youtube.com/watch?v=8LB7e2tKWoI
- https://github.com/intellectronica/ez-mcp
~~That mutates the project/env in your cwd. They have a lot in their docs, but I think you’d like run --with or uv’s PEP723 support a lot more~~
https://docs.astral.sh/uv/guides/scripts/
Also love Ruff from the Astral team. We just cut our linting + formatting across from pylint + Black to Ruff.
Saw lint times drop from 90 seconds to < 1.5 seconds. crazy stuff.