956 palabras
5 minutos
UV Init - Proyectos y flujos de trabajo

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 run sincroniza y ejecuta en un solo paso.
  • Reproducibilidad real: uv.lock guarda 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#

TareaInterfaz uv pipModo proyecto
Crear entornouv venvuv init (el entorno se crea solo)
Instalar paqueteuv pip install paqueteuv add paquete
Desinstalaruv pip uninstall paqueteuv remove paquete
Ver dependenciasuv pip treeuv tree
Replicar entornouv pip install -r requirements.txtuv sync
Ejecutarsource .venv/bin/activateuv run comando

1. Crear un proyecto#

Inicializar#

Terminal window
uv init mi_proyecto
cd mi_proyecto

O, si ya estás dentro de la carpeta:

Terminal window
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 dependencias

El 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 = []
TIP

El .venv y el uv.lock no se crean con uv init. Aparecen la primera vez que ejecutas uv add, uv sync o uv run.

Elegir la versión de Python#

Terminal window
# Al crear el proyecto
uv init mi_proyecto --python 3.12
# En un proyecto existente
uv python pin 3.12

Si no tienes esa versión instalada, uv la descarga automáticamente.

2. Gestionar dependencias#

Añadir paquetes#

Terminal window
uv add requests
# Con versión específica
uv add requests==2.32.3
# Con un rango de versiones
uv 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.):

Terminal window
uv add --dev pytest ruff

Eliminar paquetes#

Terminal window
uv remove requests

Ver el árbol de dependencias#

Terminal window
uv tree

3. Ejecutar código#

Con uv run#

Terminal window
uv run main.py
uv run python -c "import requests; print(requests.__version__)"
uv run pytest

Antes 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#

Terminal window
echo "alias uvs='source .venv/bin/activate'" >> ~/.bashrc

Activar el entorno en modo manual#

Terminal window
source .venv/bin/activate

4. Replicar un proyecto#

Este es el punto fuerte del modo proyecto. Si alguien clona tu repositorio:

Terminal window
git clone https://github.com/usuario/mi_proyecto.git
cd mi_proyecto
uv sync

Listo: misma versión de Python y mismas versiones exactas de cada paquete.

IMPORTANT

Sube el uv.lock a 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:

Terminal window
uv sync --no-dev

Fallar si el lock no está al día#

Útil en CI, para asegurarte de que nadie olvidó actualizar el uv.lock:

Terminal window
uv sync --locked

5. Actualizar dependencias#

Terminal window
# Actualizar todas las dependencias (respetando los rangos del pyproject.toml)
uv lock --upgrade
# Actualizar solo un paquete
uv lock --upgrade-package requests
# Aplicar los cambios al entorno
uv sync

6. Migrar desde requirements.txt#

Importar#

Terminal window
uv init
uv add -r requirements.txt

Exportar#

Si alguien necesita un requirements.txt (por ejemplo, una herramienta que no soporta uv):

Terminal window
uv export --format requirements-txt > requirements.txt

Ejemplos#

Ejemplo Frida y Objection#

El mismo ejemplo del UV Cheatsheet, ahora en modo proyecto:

Terminal window
# Creamos el proyecto
uv init 16.5.2 && cd 16.5.2
# Añadimos las herramientas que necesitamos
uv add frida==16.5.2 frida-tools objection==1.11.0
# Corroboramos que todo funcione
uv run frida --version
# 16.5.2
# Ejemplo con un script
# uv run frida -U -f com.app.app -l script.js
TIP

Al fijar frida==16.5.2, uv elige automáticamente una versión de frida-tools compatible con ella. Con pip, a veces terminas con una versión de frida-tools que pide otra versión de frida.

Ejemplo xcat con una versión específica de Python#

Terminal window
# Creamos el proyecto con Python 3.10
uv init xcat_uv --python 3.10 && cd xcat_uv
# Añadimos xcat
uv add xcat
# Corroboramos que todo funcione
uv run xcat --version
NOTE

Si solo quieres usar una herramienta de línea de comandos (como xcat) y no vas a escribir código alrededor de ella, uv tool es más cómodo:

Terminal window
uv tool install xcat --python 3.10
xcat --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:

Terminal window
uv init --script scan.py --python 3.12
uv add --script scan.py requests rich
uv run scan.py

uv 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#

Terminal window
uv init [nombre] # Crear proyecto
uv init --python 3.12 # Crear proyecto con versión de Python
uv python pin 3.12 # Cambiar la versión de Python
uv add paquete # Añadir dependencia
uv add --dev paquete # Añadir dependencia de desarrollo
uv remove paquete # Eliminar dependencia
uv tree # Ver árbol de dependencias
uv run comando # Ejecutar dentro del entorno
uv sync # Sincronizar entorno con uv.lock
uv sync --no-dev # Sincronizar sin dependencias de desarrollo
uv lock --upgrade # Actualizar todas las dependencias
uv lock --upgrade-package p # Actualizar un paquete
uv add -r requirements.txt # Importar requirements.txt
uv export --format requirements-txt > requirements.txt # Exportar
Nota 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:

UV Init - Proyectos y flujos de trabajo
https://elcaza.github.io/posts/sysadmin/uv_init/
Autor
El Capitán
Publicado el
2026-10-29
Licencia
CC BY-NC-SA 4.0