En proyectos de mayor envergadura es común encontrarse con que pip, el gestor de paquetes por defecto de Python, no proporciona todas las funcionalidades que uno necesita para manejar de manera cómoda las dependencias de su aplicación o librería.

Poetry es una gestor que cubre muchas de sus carencias: permite fijar versiones para poder replicar fácilmente el entorno, marcar las dependencias que se utilizan únicamente durante el desarrollo, resolver conflictos entre paquetes facilitando así su actualización, etc. Es también capaz de crear entornos virtuales, aislando así las dependencias entre proyectos y centralizando todo lo relacionado con la gestión de paquetes en una única herramienta.

Sébastien Eustace, conocido también por su librería pendulum, crea Poetry en 2018 con la intención de tener una única herramienta capaz de empaquetar librerías y gestionar dependencias haciendo uso de un solo archivo de configuración.

Inspirado en herramientas como composer (PHP) y cargo (Rust), reemplaza los archivos de: setup.py, setup.cfg, requirements.in, requirements.txt, MANIFEST.in, entre otros, con un único archivo pyproject.toml estandarizado en el PEP-518.

[tool.poetry]
name = "mi-libreria"
version = "0.1.0"
description = "Una librería super guay"
authors = ["Xiang Chen <xchen@paradigmadigital.com>"]
readme = 'README.md'
repository = "https://github.com/python-poetry/poetry"
homepage = "https://python-poetry.org/"
keywords = ['packaging', 'poetry']

[tool.poetry.dependencies]
python = "^3.7" # versiones python compatibles
fastapi = "^0.70.0"
celery = { version = "^5.12", extras = ["redis"] }
cleo = { git = "https://github.com/sdispater/cleo.git", branch = "master" }

[tool.poetry.dev-dependencies] # dependencias de desarrollo
pytest = "^6.2.5"
black = "^21.9b0"
isort = "^5.9.3"

[tool.isort]  # configuración para herramientas concretas
profile = "black"

[build-system]  # permite hacer pip install de la carpeta directamente
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

Instalación y configuración

La manera recomendada de instalar poetry es mediante el script proporcionado por sus desarrolladores:

curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | python -
(Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py -UseBasicParsing).Content | python -

Nota: No se recomienda instalarlo globalmente con pip ya que algunas de sus dependencias podrían entrar en conflicto con otras librerías del sistema. En caso de no querer hacer un curl, otra alternativa que proponen en su web es instalarlo vía pipx.

Recomendamos anotar la ruta que imprime la ejecución por si es necesario añadirlo a la variable PATH más adelante. Para comprobar que todo haya ido correctamente, podemos ejecutar en una nueva terminal:

poetry --version

Una vez instalado ya podremos ir a nuestro proyecto y crear el archivo pyproject.toml interactivamente:

poetry init

Antes de crear el entorno y añadir dependencias, recomendamos crear un archivo poetry.toml con el siguiente contenido:

[virtualenvs]
create = true
in-project = true

Esto hará que el entorno virtual se cree en una carpeta .venv en el mismo proyecto y no en algún lugar perdido de la faz de la tierra (~/.cache/pypoetry/virtualenvs).

Tras ejecutar poetry install, el proyecto debería tener la siguiente estructura:

mi-proyecto
├── .venv/
├── poetry.lock
├── poetry.toml
└── pyproject.toml

Nota: Si estamos creando un nuevo proyecto podemos también ejecutar directamente:
poetry new mi-proyecto

Gestión de dependencias

En el paso anterior hemos visto que Poetry ha generado un archivo llamado poetry.lock al crear el entorno. Al igual que hacen los gestores de dependencias de otros lenguajes como npm o cargo, se trata de un archivo que bloquea las dependencias y permite replicar el entorno en cualquier lugar y momento. El archivo indica para cada dependencia su versión, su hash y, en caso de ser una dependencia de git, el commit concreto.

Algunos ejemplos para añadir una dependencia son:

poetry add flask
poetry add --dev pytest
poetry add "git+https://github.com/ansible/ansible.git@v2.11.6"}

Otros comandos interesantes son:

En proyectos profesionales es posible que sea necesario utilizar un pypi privado, para ello tendríamos que modificar el pyproject.toml directamente:

[tool.poetry.dependencies]
pendulum = {version = "^2.0", source = "custom-pypi"}

[[tool.poetry.source]]
name = "custom-pypi"
url = "https//example.com/simple"

Entorno virtual

Para ejecutar comandos dentro el entorno virtual tendremos que añadir el prefijo de "poetry run" a todo lo que ejecutemos:

poetry run pytest
poetry run python main.py
poetry run gunicorn -w 4 myapp:app

También podemos simplemente ejecutar "poetry shell" o lanzar el script de activación del entorno correspondiente al nuestro sistema operativo:

source .venv/bin/activate
.\.venv\Scripts\activate.ps1

Otros comandos útiles para la gestión del entorno virtual son: poetry env info, poetry env list y poetry env remove.

Empaquetado y distribución de librerías

Para generar una carpeta dist/ que contenga tanto el archivo .tar.gz como el archivo .whl de nuestra librería, únicamente debemos ejecutar:

poetry build

De la misma manera, para subir la librería a PyPI bastaría con ejecutar:


poetry publish

Alternativas

La principal alternativa a Poetry es Pipenv: este soluciona de manera elegante el problema de resolución de dependencias y gestión del entorno pero tiene también sus defectos:

Otra opción más tradicional podría ser utilizar las propias herramientas que ofrece Python, es decir, pip, setup.py, requirements.txt y venv; e introducir pip-tools únicamente si el proyecto necesita la funcionalidad de resolver dependencias. El problema de este enfoque es la mayor curva de aprendizaje para principiantes y el gran número de archivos de configuración que añade al proyecto.

Conclusiones

¿Es entonces poetry la solución a todos los problemas? Aunque parezca que sí, nada es perfecto:

Dicho esto, en la mayoría de los proyectos poetry podría ser una muy buena opción al facilitar las actualizaciones de dependencias y reducir el número de herramientas y de archivos de configuración del proyecto.

Cuéntanos qué te parece.

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.

Suscríbete