uv — Gestionando +80 entornos virtuales en producción
En este artículo comparto nuestra experiencia:
- Cómo acortamos de días a minutos el setup para los nuevos onboardings.
- Reemplazando nuestro stack (pip, pyenv y virtualenv) por una sola herramienta (uv).
- Gestionando +80 entornos virtuales de Python en producción.
- Limpiando +20 GB de entornos zombies.
- Acelerando todos nuestros
run,buildydeployshasta 10x.
¿Qué es uv?
uv es un gestor de paquetes y proyectos de Python extremadamente rápido, escrito en Rust. Su objetivo es reemplazar múltiples herramientas de Python como pip, poetry, pyenv y virtualenv con una única solución de alto rendimiento.
Características principales
- Reemplaza
pip,poetry,pyenv,virtualenv, etc. por una sola herramienta. - Está escrita en Rust, lo que la hace 10-100 veces más rápida que
pip. - Compatible con
pyproject.tomly archivos.lock. - Eficiente en el uso del espacio en disco, con un caché global para la deduplicación de dependencias.
uv cuenta con el respaldo de Astral, los creadores de Ruff.

Instalación
Instala uv siguiendo los pasos de la guía oficial de instalación.
Uso básico
Gestión de versiones de Python
# Instalar versiones de Python
uv python install 3.10 3.11 3.12
# Crear entorno virtual con versión específica de Python
uv venv --python 3.11
Gestión de proyectos
# --- Primera vez ---
# Inicializar un nuevo proyecto
uv init mi_proyecto
# Crear un entorno virtual
uv venv
# --- Agregar dependencias ---
# Activar el entorno virtual
# En Linux/macOS
source .venv/bin/activate
# En Windows
# .venv\Scripts\activate
# Añadir/Quitar dependencias iniciales
uv add requests pandas numpy
uv remove pandas
# Sincronizar dependencias basadas en el archivo de bloqueo
uv sync
Ejecución de scripts
# Ejecutar un script Python con dependencias
uv run script.py
# Añadir dependencias a un script
uv add --script script.py requests
Gestión de herramientas
# Ejecutar una herramienta en un entorno efímero
uvx ruff check .
# Instalar una herramienta
uv tool install ruff
Para información más detallada y guías, visitá la documentación oficial de uv.
Gestionando entornos en producción con uv
Problema y contexto
Nuestro contexto: repos con más de 300 DAGs de Airflow (MWAA) corriendo sobre EC2, con más de 80 scripts, cada uno con su propio entorno virtual y su requirements.txt. El onboarding de un nuevo desarrollador implicaba instalar pyenv, crear y activar entornos manualmente, e instalar dependencias con pip uno por uno.

Esto generaba varios problemas:
- Onboarding chaos: setup de PC lento, commits sin tests o deploys con fallos.
- Gestión manual de venvs: instalar y mantener entornos a mano en EC2.
- Storage full: entornos zombies acumulando espacio en disco.
Toda esta carga operativa recayó sobre el equipo, así que decidimos implementar uv y adoptar dos estrategias.

Estrategias de implementación
Entornos administrados
Para procesos recurrentes con dependencias estables, mantenemos un entorno virtual por proyecto, versionado junto al código.

# ADMIN
mkdir <proyecto>
cd <proyecto>
uv init
# Completar el pyproject.toml:
# [] Descripción y nombre del proyecto
# [] Author y README.md
# [] Versión de Python
uv venv --python 3.X
# uv sync
source .venv/bin/activate
uv add requests
# uv remove requests
# DEV
cd <proyecto>
# uv sync
uv run main.py
Entornos efímeros
Para scripts puntuales o de uso esporádico, usamos entornos efímeros: uv resuelve e instala las dependencias declaradas directamente en el script, sin necesidad de mantener un .venv persistente.

# /// script
# requires-python = ">=3.12"
# dependencies = [
# "boto3",
# "requests"
# ]
# ///
import boto3
import requests
# ... resto del código
# uv run main.py
Impacto y beneficio

- +80 venvs en producción, gestionados con una sola herramienta.
- Fricción en el setup: de días a minutos.
- 3 herramientas (
pip,pyenv,virtualenv) reemplazadas por uv. - -20 GB de entornos zombies y duplicados eliminados.
- 10x de mejora en
run,buildydeploy.
Tip: si tenés múltiples scripts independientes con pocas dependencias, preferí entornos efímeros con metadata inline (
uv run script.py) en vez de mantener un.venvpor cada uno — te ahorra limpieza y espacio en disco.
