Introducción
En el UV Cheatsheet usamos uv a través de su interfaz uv pip, que funciona como un pip mucho más rápido. Pero uv tiene un modo de trabajo propio: el modo proyecto.
En este modo ya no instalas paquetes “a mano” en un entorno. Declaras las dependencias en un archivo pyproject.toml y uv se encarga del resto: crea el entorno, instala lo necesario y guarda las versiones exactas en un archivo de bloqueo (uv.lock).
¿Por qué usar el modo proyecto?
- Sin activar entornos:
uv runsincroniza y ejecuta en un solo paso. - Reproducibilidad real:
uv.lockguarda la versión exacta de todas las dependencias, incluidas las indirectas. - Un solo comando para replicar: quien clone tu proyecto solo necesita ejecutar
uv sync. - Gestión de Python incluida: uv descarga la versión de Python que el proyecto necesite.
uv pip vs modo proyecto
| Tarea | Interfaz uv pip | Modo proyecto |
|---|---|---|
| Crear entorno | uv venv | uv init (el entorno se crea solo) |
| Instalar paquete | uv pip install paquete | uv add paquete |
| Desinstalar | uv pip uninstall paquete | uv remove paquete |
| Ver dependencias | uv pip tree | uv tree |
| Replicar entorno | uv pip install -r requirements.txt | uv sync |
| Ejecutar | source .venv/bin/activate | uv run comando |
1. Crear un proyecto
Inicializar
uv init mi_proyectocd mi_proyectoO, si ya estás dentro de la carpeta:
uv init¿Qué se crea?
mi_proyecto/├── .git/├── .gitignore├── .python-version # Versión de Python del proyecto├── README.md├── main.py # Script de ejemplo└── pyproject.toml # Metadatos y dependenciasEl pyproject.toml inicial luce así:
[project]name = "mi_proyecto"version = "0.1.0"description = "Add your description here"readme = "README.md"requires-python = ">=3.12"dependencies = []TIPEl
.venvy eluv.lockno se crean conuv init. Aparecen la primera vez que ejecutasuv add,uv syncouv run.
Elegir la versión de Python
# Al crear el proyectouv init mi_proyecto --python 3.12
# En un proyecto existenteuv python pin 3.12Si no tienes esa versión instalada, uv la descarga automáticamente.
2. Gestionar dependencias
Añadir paquetes
uv add requests
# Con versión específicauv add requests==2.32.3
# Con un rango de versionesuv add "requests>=2.31,<3"Cada uv add actualiza tres cosas a la vez: el pyproject.toml, el uv.lock y el .venv.
Dependencias de desarrollo
Paquetes que solo necesitas mientras desarrollas (tests, linters, etc.):
uv add --dev pytest ruffEliminar paquetes
uv remove requestsVer el árbol de dependencias
uv tree3. Ejecutar código
Con uv run
uv run main.pyuv run python -c "import requests; print(requests.__version__)"uv run pytestAntes de ejecutar, uv run comprueba que el entorno esté sincronizado con el uv.lock. Si falta algo, lo instala. Por eso no hace falta activar nada.
Activando el entorno (si lo prefieres)
El modo proyecto sigue usando un .venv normal, así que el alias del post anterior sigue funcionando:
Generar alias
echo "alias uvs='source .venv/bin/activate'" >> ~/.bashrcActivar el entorno en modo manual
source .venv/bin/activate4. Replicar un proyecto
Este es el punto fuerte del modo proyecto. Si alguien clona tu repositorio:
git clone https://github.com/usuario/mi_proyecto.gitcd mi_proyectouv syncListo: misma versión de Python y mismas versiones exactas de cada paquete.
IMPORTANTSube el
uv.locka tu repositorio. Es lo que garantiza que todos tengan exactamente el mismo entorno. El.venv, en cambio, no se sube (ya viene en el.gitignore).
Instalar sin dependencias de desarrollo
Útil para servidores o contenedores:
uv sync --no-devFallar si el lock no está al día
Útil en CI, para asegurarte de que nadie olvidó actualizar el uv.lock:
uv sync --locked5. Actualizar dependencias
# Actualizar todas las dependencias (respetando los rangos del pyproject.toml)uv lock --upgrade
# Actualizar solo un paqueteuv lock --upgrade-package requests
# Aplicar los cambios al entornouv sync6. Migrar desde requirements.txt
Importar
uv inituv add -r requirements.txtExportar
Si alguien necesita un requirements.txt (por ejemplo, una herramienta que no soporta uv):
uv export --format requirements-txt > requirements.txtEjemplos
Ejemplo Frida y Objection
El mismo ejemplo del UV Cheatsheet, ahora en modo proyecto:
# Creamos el proyectouv init 16.5.2 && cd 16.5.2
# Añadimos las herramientas que necesitamosuv add frida==16.5.2 frida-tools objection==1.11.0
# Corroboramos que todo funcioneuv run frida --version# 16.5.2
# Ejemplo con un script# uv run frida -U -f com.app.app -l script.jsTIPAl fijar
frida==16.5.2, uv elige automáticamente una versión defrida-toolscompatible con ella. Con pip, a veces terminas con una versión defrida-toolsque pide otra versión defrida.
Ejemplo xcat con una versión específica de Python
# Creamos el proyecto con Python 3.10uv init xcat_uv --python 3.10 && cd xcat_uv
# Añadimos xcatuv add xcat
# Corroboramos que todo funcioneuv run xcat --versionNOTESi solo quieres usar una herramienta de línea de comandos (como xcat) y no vas a escribir código alrededor de ella,
uv tooles más cómodo:Terminal window uv tool install xcat --python 3.10xcat --version
Bonus: scripts sueltos con dependencias
¿Un script de un solo archivo que necesita librerías? No hace falta crear un proyecto. uv puede guardar las dependencias dentro del propio script:
uv init --script scan.py --python 3.12uv add --script scan.py requests richuv run scan.pyuv añade un bloque como este al inicio del archivo:
# /// script# requires-python = ">=3.12"# dependencies = [# "requests",# "rich",# ]# ///Puedes compartir solo el .py y quien lo reciba lo ejecuta con uv run scan.py, sin instalar nada a mano.
Cheatsheet rápido
uv init [nombre] # Crear proyectouv init --python 3.12 # Crear proyecto con versión de Pythonuv python pin 3.12 # Cambiar la versión de Pythonuv add paquete # Añadir dependenciauv add --dev paquete # Añadir dependencia de desarrollouv remove paquete # Eliminar dependenciauv tree # Ver árbol de dependenciasuv run comando # Ejecutar dentro del entornouv sync # Sincronizar entorno con uv.lockuv sync --no-dev # Sincronizar sin dependencias de desarrollouv lock --upgrade # Actualizar todas las dependenciasuv lock --upgrade-package p # Actualizar un paqueteuv add -r requirements.txt # Importar requirements.txtuv export --format requirements-txt > requirements.txt # ExportarNota final¡Gracias por terminar de leer este artículo! uwur
— El Capitán
¿Tienes alguna duda o te gustaría comentar algo sobre este artículo?
Puedes encontrarme en: