Qué es uv y por qué ha cambiado el ecosistema
flowchart TD
UV["uv (Astral, Rust)"] --> INIT["uv init: nuevo proyecto"]
UV --> ADD["uv add / remove: dependencias"]
UV --> SYNC["uv sync: instalar lock"]
UV --> LOCK["uv.lock: bloqueo reproducible"]
UV --> RUN["uv run: ejecuta scripts"]
UV --> TOOL["uv tool: instala herramientas (pipx)"]
UV --> PY["uv python: gestión de intérpretes (pyenv)"]
UV -.->|reemplaza| LEGACY["pip + venv + pip-tools + pipx + pyenv"]
uv es un gestor de paquetes y proyectos Python desarrollado por Astral, la misma empresa que creó el linter ruff. Está escrito en Rust y su objetivo es reemplazar pip, venv, pip-tools, pipx y pyenv con una única herramienta que hace todo lo que antes requería combinar varias.
Sus dos propuestas de valor son la velocidad y la simplificación. En benchmarks habituales, uv es entre 10 y 100 veces más rápido que pip porque resuelve dependencias en paralelo y mantiene una caché global compartida entre proyectos. La instalación de dependencias grandes como numpy o torch pasa de minutos a segundos.
uv no es solo un pip más rápido: es una herramienta de proyecto completa al estilo de Cargo (Rust) o Poetry, con bloqueo de dependencias, scripts y gestión de intérpretes Python integrada.
A día de hoy uv es el estándar de facto para proyectos Python nuevos en empresas modernas. Equipos que antes usaban pip + venv + pip-tools han migrado en bloque porque el flujo de trabajo es más simple y los tiempos de CI bajan drásticamente.
Instalación de uv
uv se instala como un binario autónomo, sin depender de Python previamente instalado. Es portable y no interfiere con las instalaciones de Python del sistema.
En macOS y Linux:
curl -LsSf https://astral.sh/uv/install.sh | sh
En Windows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Tras instalar, verifica que el comando está disponible:
uv --version
Una vez instalado, uv puede gestionar sus propias actualizaciones:
uv self update
Crear un proyecto con uv
El flujo moderno empieza por uv init, que crea la estructura de un proyecto Python con pyproject.toml, entorno virtual y README. No es necesario crear manualmente el venv ni el requirements.txt.
uv init mi-proyecto
cd mi-proyecto
La estructura generada contiene:
mi-proyecto/
.python-version
README.md
hello.py
pyproject.toml
El archivo pyproject.toml es el manifiesto del proyecto. Allí se declaran el nombre, la versión, las dependencias y el intérprete Python requerido:
[project]
name = "mi-proyecto"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = []
El archivo .python-version fija la versión de Python que debe usar el proyecto, y uv la respeta automáticamente sin necesidad de herramientas externas como pyenv.
Gestionar dependencias
Para añadir una dependencia, se usa uv add. A diferencia de pip install, uv add actualiza automáticamente pyproject.toml, crea el entorno virtual si no existe y regenera el archivo de bloqueo uv.lock.
uv add requests
uv add "fastapi>=0.115" "uvicorn[standard]"
Para dependencias de desarrollo (tests, linters, formatters), usa la bandera --dev:
uv add --dev pytest pytest-cov ruff
Estas quedan aisladas en un grupo separado, se instalan en desarrollo pero no se incluyen cuando alguien instala tu paquete como dependencia.
Para eliminar una dependencia:
uv remove requests
Bloqueo reproducible con uv.lock
Uno de los grandes problemas del pip tradicional es que pip install -r requirements.txt no garantiza que dos máquinas obtengan exactamente las mismas versiones. uv soluciona esto con uv.lock, un archivo generado automáticamente que fija las versiones exactas de todas las dependencias directas y transitivas.
Cada vez que ejecutas uv add, uv actualiza el lock. Para sincronizar el entorno al estado exacto del lock:
uv sync
Este comando instala las versiones exactas registradas en uv.lock, garantizando reproducibilidad entre desarrolladores y entre entornos (local, CI, producción). Es el equivalente a npm ci en Node o cargo build --locked en Rust.
Commits típicos:
pyproject.tomlyuv.lockvan siempre al repositorio. El directorio.venv/se añade a.gitignore. Cualquier persona que clone el repo reconstruye el entorno idéntico con un solouv sync.
Ejecutar código y herramientas
uv run ejecuta cualquier comando dentro del entorno virtual del proyecto sin necesidad de activarlo manualmente.
uv run python app.py
uv run pytest
uv run ruff check .
Es mucho más práctico que source .venv/bin/activate en cada terminal nueva.
Para herramientas globales (equivalente a pipx), usa uv tool:
uv tool install ruff
uv tool install httpie
ruff check .
uv tool instala cada herramienta en su propio entorno aislado, igual que pipx, pero con la velocidad y la caché compartida de uv.
Gestionar versiones de Python
uv integra la instalación de intérpretes, cubriendo el rol de pyenv:
uv python install 3.13
uv python install 3.12 3.11
uv python list
Para usar una versión concreta en un proyecto:
uv python pin 3.13
Esto actualiza el archivo .python-version y uv descargará e instalará esa versión si no la tienes.
Scripts independientes con PEP 723
Una funcionalidad moderna es ejecutar scripts sueltos con dependencias declaradas en el propio archivo, siguiendo el estándar PEP 723.
# analizar.py
# /// script
# requires-python = ">=3.13"
# dependencies = [
# "requests",
# "rich",
# ]
# ///
import requests
from rich import print
r = requests.get("https://api.github.com/repos/astral-sh/uv")
print(r.json()["stargazers_count"])
uv run analizar.py
uv detecta las dependencias del script, crea un entorno efímero, las instala y ejecuta el archivo. Ideal para scripts de automatización que necesitan librerías sin crear un proyecto entero.
Flujo de trabajo completo
Un día a día típico con uv se reduce a cuatro comandos:
uv init mi-app # crear proyecto
uv add fastapi pydantic # añadir dependencias de producción
uv add --dev pytest ruff # añadir dependencias de desarrollo
uv sync # instalar todo lo del lock
uv run python src/main.py # ejecutar
uv run pytest # tests
uv run ruff check . # linter
Con esto reemplazas por completo la combinación clásica de python -m venv, source .venv/bin/activate, pip install, pip freeze > requirements.txt, pyenv install, pyenv local y pipx install.
Migración desde requirements.txt
Si tienes un proyecto con requirements.txt, puedes migrarlo en un paso:
uv init --lib mi-lib # o uv init para app
uv add -r requirements.txt
Esto importa cada línea de requirements.txt al pyproject.toml y genera el uv.lock correspondiente. Tras verificar, puedes archivar o eliminar el requirements.txt antiguo.
Para exportar compatibilidad temporal con herramientas que aún dependen de requirements.txt (CI antiguos, Dockerfiles):
uv export --format requirements-txt > requirements.txt
Esto regenera el fichero a partir del lock en cualquier momento, sin perder la fuente de verdad que vive en pyproject.toml y uv.lock.
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Python es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Python
Explora más contenido relacionado con Python y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Instalar uv en cualquier sistema operativo. Crear proyectos Python con uv init y gestionar dependencias con uv add y uv remove. Sincronizar entornos reproducibles con uv sync y uv lock. Ejecutar scripts y herramientas con uv run y uv tool. Instalar y cambiar entre versiones de Python con uv python.