Una forma sencilla de gestionar las dependencias en tu proyecto.
Desarrollar una aplicación en Python actualmente, requiere un control exhaustivo de las dependencias que en muchos casos, las soluciones actuales, no proveen ó en el peor de los casos... Que tú mismo lo resuelvas como puedas...
Poetry es una herramienta para la gestión de dependencias y empaquetado en Python. Te permite declarar las bibliotecas de las que depende tu proyecto y las gestionará por ti.
Hasta aquí, nada nuevo bajo el sol, de momento...
-- un visitante del blog
Correcto, Lo mágico de Poetry, es lo que ofrece y la forma como ofrece la gestión de las dependencias. 🎉
- 📌 Información relevante del proyecto en un solo sitio.
- 📝 Dependencias del proyecto.
- 🚦 Dependencias opcionales.
- 🎮 Dependencias de desarrollo.
- 🏁 Configuración para herramientas de terceros en tu proyecto (black, isort, etc...).
- 🚀 Scripting para ampliar las necesidades de tu proyecto.
- 📦 Plugins para ampliar las capacidades de Poetry.
- Y...muchas funcionalidades 😄
Instalación
Poetry requiere Python3.7 ó superior, para nuestro ejemplo, usaremos Python3.9
❯ curl -sSL https://install.python-poetry.org | python3.9 -
Al momento de escribir este post:
❯ poetry --version
Poetry version 1.1.12
Iniciando
De aquí en adelante no usaremos el tradicional archivo requirements.txt
Espera... qué?
-- un visitante del blog
En vez de eso, utilizaremos un archivo llamado pyproject.toml en el cual estará toda la información de la gestión de las dependencias y todo lo que comentamos anteriormente.
El archivo pyproject.toml utiliza la sintaxis toml y su configuración, para proyectos de Python, está detallada en el PEP 518.
Poetry permite definir secciones, para el nombre de nuestro proyecto, la versión, el autor ó los autores, la licencia etc....
Ejemplo:
[tool.poetry]
name = "my awesome project"
version = "1.0.0"
description = "awesome project with poetry"
authors = ["Jorge Brunal Pérez <diniremix@gmail.com>"]
license = "LGPL-2.1-only"
readme = "README.md"
ademas de:
- homepage: La página de presentación de nuestro proyecto (usualmente la url del repositorio).
- repository: La dirección web del repositorio.
- documentation. La dirección web de la documentación.
- keywords: Una lista de palabras clave (máximo: 5) con las que el proyecto está relacionado.
- classifiers: Una lista de clasificadores de PyPI que describen el proyecto.
- urls: Además de las urls básicas (página de inicio, repositorio y documentación), puede especificar cualquier url personalizada en esta sección.
Ejemplo:
[tool.poetry]
homepage = "https://awesome-site.org/projects/awesome-project"
repository = "https://gitlab.com/awesome-user/awesome-repo"
documentation = "https://awesome-site.org/docs/awesome-project"
keywords = ["awesome", "flask", "python"]
classifiers = [
"Framework :: Flask",
"License :: OSI Approved :: GNU Lesser General Public License v2 (LGPLv2)",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3.9",
"Development Status :: 5 - Production/Stable",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Utilities",
]
[tool.poetry.urls]
"Bug Tracker" = "https://gitlab.com/awesome-user/awesome-repo/-/issues"
El PEP 517 introduce una forma estándar de definir sistemas de construcción alternativos para construir un proyecto Python. Poetry es compatible con PEP-517, proporcionando una biblioteca de núcleo ligero, por lo que debemos hacer referencia a él, agregando una sección llamada build-system en nuestro archivo pyproject.toml:
Ejemplo:
[build-system]
requires = ["poetry-core>=1.1.0"]
build-backend = "poetry.core.masonry.api"
Muy bonito y todo pero... y las depedencias...
-- un visitante del blog
Sigue leyendo 👇
Manejando las Dependencias 🚚
En tu archivo pyproject.toml define la lista de dependencias:
# lista de las dependencias básicas
[tool.poetry.dependencies]
# Tenga en cuenta que es obligatorio declarar la versión de python
# para la que su proyecto ó paquete es compatible
python = "~3.9"
Flask="2.0.1"
SQLAlchemy="1.4.25"
Flask-SQLAlchemy="2.5.1"
jsonschema="4.0.1"
loguru="0.5.3"
# se definen dependencias opcionales
# algunas de las cuales se incluyen mas abajo
# en la sección "extras"
PyMySQL = { version = "0.10.1", optional = true }
pandas = { version = "1.2.2", optional = true }
# lista de dependencias opcionales
[tool.poetry.extras]
mysql = ["PyMySQL"]
pandas = ["pandas"]
# dependecias de desarrollo
[tool.poetry.dev-dependencies]
black = "21.10b0"
pylint = "2.11.1"
isort = "^5.10.1"
Como habrás notado, las secciones permiten separar cada conjunto de dependencias 🎉 😏
En este punto, llevamos lo siguiente:
- Información relevante del proyecto en un solo sitio.
- Dependencias del proyecto.
- Dependencias opcionales.
- Dependencias de desarrollo.
Creación del Entorno de trabajo
En otras ocasiones crearías un entorno virtual con virtualenv, pyenv, Pipenv etc... luego entrarías a ese entorno (activarlo) y se procedería a instalar las dependencias, usando pip ó pipenv.
Poetry se encarga de manera transparente de toda estas operaciones a través de su linea de comandos. 💻 🚀
Creamos la carpeta donde se instalarán las librerías y utilizamos la versión de Python que especificamos en el pyproject.toml.
❯ poetry env use python3.9
La salida será algo como:
Creating virtualenv my awesome project in /home/diniremix/awesome-project/.venv
Using virtualenv: /home/diniremix/awesome-project/.venv
Si revisamos la carpeta de trabajo...
❯ ls -la
total 16
drwxr-xr-x 3 diniremix diniremix 4096 feb 11 21:48 .
drwxr-xr-x 10 diniremix diniremix 4096 feb 11 21:46 ..
-rw-r--r-- 1 diniremix diniremix 1636 feb 11 21:47 pyproject.toml
drwxr-xr-x 4 diniremix diniremix 4096 feb 11 21:48 .venv
El comando anterior ha creado la carpeta .venv donde se instalarán todas las dependencias, esto incluye las de desarollo, las opcionales, scripts etc...
En este momento, antes de instalar las dependencias, tu archivo pyproject.toml debe lucir como sigue:
[tool.poetry]
name = "my awesome project"
version = "1.0.0"
description = "awesome project with poetry"
authors = ["Jorge Brunal Pérez <diniremix@gmail.com>"]
license = "LGPL-2.1-only"
readme = "README.md"
homepage = "https://awesome-site.org/projects/awesome-project"
repository = "https://gitlab.com/awesome-user/awesome-repo"
documentation = "https://awesome-site.org/docs/awesome-project"
keywords = ["awesome", "flask", "python"]
classifiers = [
"Framework :: Flask",
"License :: OSI Approved :: GNU Lesser General Public License v2 (LGPLv2)",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3.9",
"Development Status :: 5 - Production/Stable",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Utilities",
]
[tool.poetry.urls]
"Bug Tracker" = "https://gitlab.com/awesome-user/awesome-repo/-/issues"
[tool.poetry.dependencies]
python = "~3.9"
Flask="2.0.1"
SQLAlchemy="1.4.25"
Flask-SQLAlchemy="2.5.1"
jsonschema="4.0.1"
loguru="0.5.3"
PyMySQL = { version = "0.10.1", optional = true }
pandas = { version = "1.2.2", optional = true }
[tool.poetry.extras]
mysql = ["PyMySQL"]
pandas = ["pandas"]
[tool.poetry.dev-dependencies]
black = "21.10b0"
pylint = "2.11.1"
isort = "^5.10.1"
[build-system]
requires = ["poetry-core>=1.1.0"]
build-backend = "poetry.core.masonry.api"
Pregunta: ¿todos los campos y secciones comentadas arriba, son obligatorias?
-- un visitante del blog
Claro que no, sin embargo ten en cuenta que la información incluida en cada sección y llave del archivo pyproject.toml, permite especificar con claridad la finalidad del proyecto, donde esta ubicado, el creador, las herramientas que usa etc...
He aquí un ejemplo de las secciones y claves requeridas:
[tool.poetry]
name = "my awesome project"
version = "1.0.0"
description = "awesome project with poetry"
authors = ["Jorge Brunal Pérez <diniremix@gmail.com>"]
[tool.poetry.dependencies]
python = "~3.9"
# al menos una dependencia
# ejemplo:
Flask="2.0.1"
[build-system]
requires = ["poetry-core>=1.1.0"]
build-backend = "poetry.core.masonry.api"
Instalar las dependencias:
❯ poetry install
La salida será algo como:
Updating dependencies
Resolving dependencies... (16.0s)
Writing lock file
Package operations: 27 installs, 0 updates, 0 removals
• Installing markupsafe (2.1.1)
• Installing click (8.0.4)
• Installing greenlet (1.1.2)
• Installing itsdangerous (2.1.1)
• Installing jinja2 (3.0.3)
• Installing lazy-object-proxy (1.7.1)
• Installing typing-extensions (4.1.1)
• Installing werkzeug (2.0.3)
• Installing wrapt (1.13.3)
• Installing astroid (2.8.6)
• Installing attrs (21.4.0)
• Installing flask (2.0.1)
• Installing isort (5.10.1)
• Installing mccabe (0.6.1)
• Installing mypy-extensions (0.4.3)
• Installing pathspec (0.9.0)
• Installing platformdirs (2.5.1)
• Installing pyrsistent (0.18.1)
• Installing regex (2022.3.15)
• Installing sqlalchemy (1.4.25)
• Installing toml (0.10.2)
• Installing tomli (1.2.3)
• Installing black (21.10b0)
• Installing flask-sqlalchemy (2.5.1)
• Installing jsonschema (4.0.1)
• Installing loguru (0.5.3)
• Installing pylint (2.11.1)
Lista de comandos útiles
# Crear el entorno.
❯ poetry env use python3.9
# Instalar todas las dependencias (incluídas las de desarollo).
❯ poetry install
# Instalar sólo las librerías principales.
❯ poetry install --no-dev
# Instalar solo las dev-dependencies
❯ poetry install --no-root
# Instalar librerías sin agregarla directamente al pyproject.toml
❯ poetry add jsonschema
# Instalar una librería de desarrollo.
❯ poetry add -D flake8
# Instalar dependencias opcionales (extras).
❯ poetry install --extras "mysql"
# ó de la forma
❯ poetry install -E mysql
# Instalar varias dependencias opcionales al tiempo.
❯ poetry install --extras "mysql pandas"
# ó de la forma
❯ poetry install -E mysql -E pandas
# Listar todas las liberías instaladas.
❯ poetry show
# Buscar una librería (mestra la info del paquete y la versión)
❯ poetry search flask
# Desinstalar una libería.
❯ poetry remove jsonschema
En la próxima entrada, usando la configuración citada arriba, agregaremos la configuración para herramientas de terceros scripting y más!