¿Buscas nuestro logo?
Aquí te dejamos una copia, pero si necesitas más opciones o quieres conocer más, visita nuestra área de marca.
¿Buscas nuestro logo?
Aquí te dejamos una copia, pero si necesitas más opciones o quieres conocer más, visita nuestra área de marca.
dev
Víctor Antonio Torre Villahoz Hace 1 día Cargando comentarios…
Cuando tenemos un proyecto un poco más grande de un script, enseguida nos vamos a ver con la necesidad de usar un gestor de paquetes, ya que vamos a necesitar alguna librería externa.
Debido a que cada librería depende o puede depender de otras librerías, al final es probable que, si instalamos a mano cada una de ellas, nos encontremos conflictos entre ellas por requerir distintas versiones de una misma librería.
Para solucionar este problema, existen los gestores de paquetes. En Python, pip (package installer for Python) ha sido el usado por defecto históricamente.
Del mismo modo, cuando trabajamos en el entorno local de desarrollo, necesitamos poder aislar un proyecto de otro. Para ello tenemos venv, que nos permite crear entornos virtuales, ya que no queremos que una de nuestras aplicaciones rompa otra al instalar las dependencias.
Por último, cuando vamos a hacer una release, necesitamos fijar la versiones de las librerías, ya que no queremos que, unos días después de nuestra release, un cambio en una librería externa rompa nuestra aplicación y crear una “build” de nuestro desarrollo para poder distribuirlo.
Al igual que poetry, UV es una herramienta que nos va a permitir solucionar todos los problemas que hemos descrito anteriormente.
Pero UV pretende ser algo más, un “Cargo para Python”. Esto quiere decir que es un único binario que contiene múltiples herramientas. UV está escrito en Rust, un lenguaje de programación compilado que permite que la velocidad de ejecución sea muy superior a otras.
Para las operaciones habituales de pip y pip-tools, en la mayoría de los casos, simplemente cambiar pip install por uv pip install funcionará sin problemas. Esto facilita enormemente la adopción en proyectos existentes. Sin embargo, UV no es un clon exacto de pip, y algunas de sus diferencias son intencionadas para ofrecer mejoras significativas, por ejemplo:
Os dejamos una comparativa entre distintas herramientas:
| Característica | pip + virtualenv | pipenv | Poetry | pdm | UV |
|---|---|---|---|---|---|
| Función principal | Instalador de paquetes + Gestor de entornos (manual) | Gestor de dependencias y entornos integrado | Gestor de proyectos completo (dependencias, build, publish) | Gestor de proyectos moderno | Gestor unificado de proyectos y herramientas de alto rendimiento |
| Archivo de configuración | requirements.txt | Pipfile | pyproject.toml | pyproject.toml | pyproject.toml |
| Archivo de bloqueo | No por defecto (requiere pip freeze) | Pipfile.lock (JSON) | poetry.lock (TOML) | pdm.lock (TOML) | uv.lock (TOML) |
| Gestión de entornos | Manual con virtualenv o venv | Automática y centralizada | Automática y por proyecto (configurable) | Automática (venv o PEP 582 opcional) | Automática y por proyecto |
| Resolución de dependencias | Básica, secuencial | Avanzada pero históricamente lenta | Avanzada y robusta | Avanzada y rápida | Avanzada y ultrarrápida |
| Soporte para publicación | No (requiere herramientas como twine) | No | Sí, integrado (poetry publish) | Sí, integrado (pdm publish) | Sí, integrado (UV publish) |
| Rendimiento | Base | Lento | Moderado | Rápido | Excepcionalmente rápido |
| Madurez / soporte | Máxima | Alta pero estancada | Muy alta | Alta, en crecimiento | Emergente, en rápido crecimiento |
| Adhesión a PEP 621 | N/A | No | Sí | Si | Sí |
UV brilla en varios aspectos, lo cual está haciendo que destaque dentro del ecosistema de herramientas de desarrollo en Python:
Empezar un nuevo proyecto con UV es sencillo: utilizamos el comando uv init. Esto generará la estructura básica necesaria:
mkdir my-uv-proj
cd my-uv-proj
uv init
También podemos usar uv init my-uv-proj, que creará la carpeta por nosotros. Tras el init, se crearán los archivos esenciales como pyproject.toml, .python-version y un simple main.py.
Ahora vamos a añadir una dependencia usando uv add. En este punto veremos cómo se crean .venv y el fichero uv.lock el entorno virtual, y el fichero pyproject.toml se modifica añadiendo la dependencia.
Por último, para ejecutar el proyecto, usaremos uv run main.py.
UV usa un fichero propio de lock uv.lock para controlar las dependencias exactas instaladas con el fin de tener reproducibilidad. A diferencia de pyproject.toml, que declara las necesidades de tu proyecto con rangos de versiones, ej requests>=2.30 en el fichero uv.lock nos encontramos la versión exacta, así como los hashes para validar el contenido.
[[package]]
name = "annotated-types"
version = "0.7.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" },
]
No obstante, el fichero uv.lock es un fichero propio de UV, pero también podemos generar el típico “requirements.txt” o el más moderno pylock.toml usando:
uv export --format requirements.txt
uv export --format pylock.toml
Es recomendable añadir el fichero de lock en el repositorio para garantizar la reproducibilidad en los distintos entornos en los que trabajemos.
En el caso de crear una librería, también podemos usar UV para crear el paquete a distribuir. Para eso necesitamos que, en el fichero de pyproject.toml, exista la sección [build-system], añadiendo a mano:
[build-system]
requires = ["uv_build>=0.7.13,<0.8"]
build-backend = "uv_build"
También podemos hacerlo ejecutando uv init --build-backend uv al iniciar el proyecto para que nos añada esos campos desde un inicio. Cuando ejecutamos uv build se creará una carpeta dist donde se alojarán los ficheros a distribuir.
Pero eso no publicará el empaquetado en ninguna parte. Para ello, debemos ejecutar uv publish, añadiendo un “index” en el pyproject.toml con el campo publish-url:
[[tool.uv.index]]
name = "pypi"
url = "https://pypi.org/simple/"
publish-url = "https://upload.pypi.org/legacy/"
Quería destacar en este punto el modo de inclusión de dependencias desde distintos repositorios, y comentar que tenemos la opción de descargar las dependencias desde diferentes orígenes según nos interese del siguiente modo:
[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cu121"
explicit = true
[tool.uv.sources]
torch = { index = "pytorch" }
httpx = { git = "https://github.com/encode/httpx", tag = "0.27.0" }
pytest = { url = "https://files.pythonhosted.org/packages/6b/77/7440a06a8ead44c7757a64362dd22df5760f9b12dc5f11b6188cd2fc27a0/pytest-8.3.3-py3-none-any.whl" }
pydantic = { path = "/path/to/pydantic", editable = true }
UV es un proyecto que pretende ser algo más que una herramienta de gestión de paquetes. Es un diseño unificado que permite tener todas las herramientas de desarrollo en una sola.
Si actualmente usas poetry, probablemente puedas sustituirlo por UV obteniendo una mejora en los tiempos. No obstante, ten en cuenta que UV aún es un proyecto en desarrollo y que habrá casos de uso que no estén aún cubiertos.
Te animo a que compruebes si puede ser útil en tu CI/CD mejorando los tiempos de ejecución.
Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.
Cuéntanos qué te parece.