UV vs Pyenv for Managing Python Development - Part 1

2026/01/22

It’s been long enough that I keep hearing about how absolutely amazing the UV package manager (technically billed as a package and project manager), that I started to try it out for running my development workflows at my day job before trying to sell the rest of my team on it. Currently we’re using Pyenv with the Pyenv virtualenv module. Pyenv has been a much better experience than trying to manually install and maintain different Python 3 versions via HomeBrew and lots of python3 -m venv type commands.

This is Part 1, since I literally have only been using uv for a little over a week and haven’t fully assessed if it’s a better replacement for Pyenv or not, at least for the team I work with. Without further delay, let’s get into it. First off, uv is blazingly fast. Both on installing versions of Python and installing packages. For anyone who’s used pip installs for more than a couple years knows how painfully long pip can be for Python dependency resolution. uv runs fast. And so far has yet to give me any issues with dependency conflicts. I’m sure I’ll get there, but for now, it’s a buttery smooth ride and welcome change to a more painful part of Python development.

Where uv has fallen apart for me so far is I’ve gotten really used to how easy and admittedly opinionated Pyenv makes managing virtual environments. The Pyenv management of virtual environments are intuitive and easy. Even with UV’s own documentation notes using the manual source /path/to/venv/bin/activate functionality, whereas with Pyenv virtualenvs, you can just type pyenv activate <virtual-environment-name>. For someone starting out their Python journey, the first method just seems onerous. Sure, you can add aliases to make the commands easier, but the whole point of using a project manager portion would be to simplify my workflow, not remember Python native commands. UV also has a very default behaviour I can’t seem to figure out the mindset on. When you’re developing with Python, usually you have more than one virtual environment and want to be able to switch between them seamlessly. You also tend to want to name the virtual env to reflect what project it contains for easy reference. Even for a data engineer like me, where my day is a mix of coding, devopsing, and data scienceing, I have 3 different virtual environments: DBT runtime, miscellaneous project I’m working on at the moment, and a Marimo notebook environment. UV defaults to creating a development environment called venv and appears biased towards wanting to use that one. This could be my lack of experience using it widely so far, and I’ll chalk it up to that so far. Reading between the lines of the documentation seemed more bent towards just using venv as a single Python environment.

One thing, which is admittedly more personal taste than anything, is I appreciate how Pyenv downloads and installs/compiles the Python version you specify specifically for the machine you’re on. On MacOS 26, I’ve had to specify a few additional dependencies installed via HomeBrew, like openssl to get the full Python to compile successfully, which is an additional annoyance, especially when you just want to get from “install Python and these tools and start coding” as quickly as possible. I suspect my ideal setup will be using Pyenv & Pyenv virtualenvs for managing the virtual environments and uv for package management speed. More to come in future parts.