Históricamente en el mundo Python uno de los mayores dolores de cabeza ha sido la creación y gestión de entornos virtuales para poder controlar qué versión de Python ejecutar e instalar nuestras dependencias. Por suerte esto es cosa del pasado gracias a herramientas como Poetry.
¿Qué es Poetry?
Poetry es una herramienta para manejar y controlar
las dependencias de nuestro proyecto. Muy similar a npm, Poetry nos va a generar
un fichero poetry.lock
que nos va a permitir “congelar” las versiones de nuestras
dependencias.
Su principal ventaja, para mí, es que de forma completamente transparente crea un entorno virtual con la versión de Python específica que le indiquemos donde instala todas las dependencias dejando nuestro ordenador limpio sin cientos de paquetes instalados en nuestro local.
Cómo instalar Poetry
Simplemente ejecutando el siguiente comando instalaremos Poetry en nuestra máquina:
curl -sSL https://install.python-poetry.org | python3 -
Una vez finalizada la instalación podemos comprobar que todo ha ido bien con el siguiente
comando poetry --version
.
Crear un proyecto con Poetry
Crear un proyecto con Poetry es realmente sencillo, basta con escribir en nuestra terminal poetry new weather_app
.
Cuando la creación haya finalizado tendremos una carpeta weather_app con la siguiente estructura:
|-- README.md
|-- pyproject.toml
|-- tests
| |-- __init__.py
|-- weather_app
|-- __init__.py
Posteriormente hablaremos del pyproject.toml el fichero más importante de Poetry.
Añadir Poetry a un proyecto existente
Si por el contrario el proyecto ya existe es muy sencillo añadirle Poetry, simplemente
ejecutando desde nuestra terminal y dentro del directorio del proyecto poetry init
y respondiendo una serie de preguntas se generará el fichero pyproject.toml.
Configurar Poetry
Como decía antes toda la configuración de Poetry está alojada en el fichero pyproject.toml.
En dicho fichero vamos a poder configurar:
- Nuestra versión de Python.
- Nuestras dependencias con sus versiones correspondientes.
- Nuestras herramientas como yapf o flake8.
Os dejo por aquí como sería una estructura básica de este fichero:
[tool.poetry]
name = "weather app"
version = "0.1.0"
description = ""
authors = []
...
[tool.poetry.dependencies]
python = "^3.10"
...
[tool.poetry.dev-dependencies]
pytest = "^7.2.0"
...
[tool.flake8]
...
[tool.yapf]
...
[build-system]
...
Como podemos ver esta forma de centralizar todo nuestra configuración es mucho más mantenible y fácil de consultar respecto a tener múltiples ficheros de configuración, uno por herramienta como se hacía históricamente.
Cómo añadir dependencias
La gestión de dependencias siempre es un problema cuando estás trabajando en un proyecto, tanto por mantenerlas como por actualizaciones inesperadas.
Por ello Poetry nos permite instalar dependencias de una forma supersencilla tanto
para código de producción poetry add kubernetes
como para dependencias únicamente
para la fase de desarrollo poetry add -D pytest
.
Para no tener problemas con las versiones de nuestras dependencias Poetry usa semantic versioning y además nos genera un fichero llamado poetry.lock que podremos incluir en nuestro repositorio garantizando que cualquier persona que se clone el repo use las mismas versiones en nuestras dependencias.
No se vosotras pero para mi tener que crear un requirements.txt
siempre me pareció
un horror y una mala práctica a la hora de trabajar, además de que solo podías utilizar
versiones concretas lo que hacía que nuestros proyectos se quedarán obsoletos rápidamente.
Cómo usar Poetry
Una vez que tenemos Poetry instalado puede ser un poco confuso como ejecutar
algunas librerías que tenemos instaladas (como por ejemplos pytest o mypy). Simplemente
necesitamos ejecutar poetry run XXXX
siendo XXXX nuestro comando:
poetry run pytest . -ra
poetry run mypy .
poetry run flake8 .
poetry run pylint ./*
poetry run yapf --diff --recursive **/*.py
Con poetry run
vamos a tener acceso a todas las dependencias como si estuviéramos
dentro de nuestro entorno virtual.
Dockerizar una app con Poetry
Un caso muy habitual para quienes desarrollamos en Python es tener múltiples proyectos cada uno con una versión diferente, uno con 3.8 y otro con 3.10. Si queremos tener instaladas múltiples versiones en la misma máquina existen herramientas como ASDF que nos facilitan la vida un montón.
Pero mi recomendación es ir un paso más allá y no tener que instalar nada en nuestra máquina haciendo uso de Docker. De esta forma podemos dockerizar nuestra app creando un fichero Dockerfile usando la imagen de Python con la versión concreta, instalar Poetry y dejar todas nuestras dependencias encapsuladas dentro de nuestra imagen:
FROM python:3.10
WORKDIR /code
COPY pyproject.toml /code
RUN pip install poetry
RUN poetry install
COPY . /code
Usar Poetry en un CI/CD (ex: GitHub Actions)
De forma muy similar a como dockerizamos nuestra app podemos generar una pipeline con nuestro CI/CD de confianza, por simplicidad voy a usar GitHub Actions.
Os dejo por aquí un ejemplo muy sencillo, sacado de este repositorio
name: weather_app
on:
push:
branches: [ "main" ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.10
uses: actions/setup-python@v3
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install poetry
poetry install
- name: Check style, format and lint
run: |
poetry run mypy .
poetry run yapf --diff --recursive **/*.py
poetry run flake8 .
poetry run pylint ./*
- name: Tests
run: poetry run pytest -n auto
Si queréis ver un proyecto más complejo (usando docker-compose) os dejo por aquí otro fichero de configuración.
Conclusiones
Como hemos podido ver en la actualidad existen alternativas como Poetry para manejar de forma mucho más cómoda el estado de nuestros proyectos, permitiéndonos no tener que instalar cientos de paquetes en nuestras máquinas y asegurando que nuestro proyecto se ejecuta siempre de la misma forma en diferentes escenarios como puede ser una pipeline o la máquina de otro miembro del equipo.
Un saludo!