DEV Community

Henk van Hoek
Henk van Hoek

Posted on

My First `uv` Install Took 15 Minutes. Here’s What Was Really Wrong.

The Python world is buzzing about uv. It is a package installer replacing pip written in Rust by Charlie Marsh and his company, Astral. It's designed as a drop-in replacement for pip and venv, claiming to be 10x to 100x faster.

I like modern tooling, I decided to integrate it into my relativly small open-source project pi-server-vm before attempting it on the larger open source project PiSelfhosting. It speeds up the actions in theGitHub workflow a lot.

But when I first ran uv pip install -e .[dev] on my project, something went terribly wrong.

My terminal just... hung.

One minute passed. Then five. At fifteen minutes, the process was still completely stuck, so unresponsive that even Ctrl+C couldn't kill it.

I thought the tool was broken. aistudio which I use as the ai agent to assist me thought it was incompatible with my system. I was ready to dismiss it as "not ready for production."

It turns out, uv wasn't the problem at all. The problem was my PC, and solving it revealed a much deeper lesson about software development.

The Diagnostic Journey: Chasing Ghosts

When a command hangs, your first instinct is to blame the command. I let aistudio propose solutions. We went through a series of logical but ultimately incorrect diagnostic steps:

  1. Is it the Antivirus? Aistudio thought it was the antivirus. Heuristic-based security software is notorious for interfering with developer tools. It sees a new executable trying to write thousands of files into a .venv directory and flags it as suspicious. We tried whitelisting uv.exe explicitly. The process still hung.
  2. Is it a Bug in uv? Maybe the tool itself had a bug in its environment detection. We tried running it with verbose flags (--verbose) and even explicitly telling it which Python executable to use (--python C:\Path\to\python.exe). Still, it hung at the very first step, before it even started resolving dependencies.

The Real Culprit: The "Strange State" of a PC

After exhausting all the software-level diagnostics, I was ready to give up. Then, I did the one thing every IT professional recommends first, and every developer tries last: I rebooted my computer., how many times did you think, "Why didn't I do this earlier".

And just like that, the problem was gone.

The 15-minute hang was caused by a low-level file system lock on my Windows machine. As a developer, I often leave my PC running for days, letting it go into sleep mode multiple times. This can sometimes lead to system drivers—especially security or file-syncing drivers—entering a "strange state" where they don't properly release their locks, causing any new process that tries to access that part of the file system to wait forever.

The reboot cleared that deadlock completely.

The True First Run of uv

With my system in a clean state, I ran the command again:

uv pip install -e .[dev]
Enter fullscreen mode Exit fullscreen mode

This time, I could see how uv really works. The process took about a minute. It wasn't instantaneous, and this is what uv's proponents call the "first-run penalty." During this initial run, uv has to:

  1. Download every package from the internet (which is fast for me as I have a fiber connection with 1Gbs).
  2. Build its global cache, storing a pristine copy of every downloaded package on my machine for future use.
  3. Resolve the dependency tree for the first time.

This caching is the key to its speed.

The Payoff: The "Super-Fast" Second Run

The magic happened the next time I needed a clean environment. I deleted my .venv folder completely and ran the exact same command again. This was the result:

Resolved 35 packages in 299ms
Prepared 1 package in 2.82s
Installed 1 package in 11ms
Enter fullscreen mode Exit fullscreen mode

The entire installation, pulling everything from the global cache, took less than three seconds. This is the speed everyone is talking about.

The Ultimate Benefit: CI/CD Workflows

While the local speed boost is nice, the real win is for automated workflows. A GitHub Action starts from a blank slate every time, By swapping pip for uv in my build_release.yml, I can significantly speed up the "setup" phase of my builds.

Here’s the simple change:

In .github/workflows/build_release.yml
This was the old step:

- name: Install dependencies
  run: pip install -e .[dev]
Enter fullscreen mode Exit fullscreen mode

This is the new, faster set of steps:

- name: Install uv
run: pipx install uv
  • name: Install dependencies with uv run: uv pip install --system -e .[dev]
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

This journey taught me a few valuable lessons that go beyond any single tool:

  1. Debug Your Environment First: When a reliable tool behaves in a completely unexpected way (like hanging for 15 minutes), the problem is often not the tool, but the environment it's running in. Which I knew already ofcourse. It is just a reminder (again).
  2. Never Underestimate a Reboot: It's a cliché for a reason. It is the simplest way to resolve deep, low-level system deadlocks that are otherwise impossible to diagnose.
  3. Understand How Caching Works: The "slowness" of a first run is often the price of admission for the incredible speed of all subsequent runs. This is true for many modern tools, not just uv. Although I never had big problems with speed of this smaller project. The thing which made me really decide to go for uv, was the GitHub actions. This was a little slow.

So, if you're thinking of trying uv, I highly recommend it. Just make sure you give it a try on a freshly booted machine to see its true potential.

Top comments (0)