• 2 heures
  • Facile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 11/09/2024

Prenez en main les fonctionnalités supplémentaires de Poetry

Lancez des scripts sophistiqués

Dans cette section, on va commencer à toucher au fichier  pyproject.toml  pour configurer des scripts personnalisés et utilisables par des applications/softwares externes à votre projet !

Illustrons cela par un cas d’usage fictif mais plausible, où l’objectif est de :

  • Simplifier l'exécution d’un un script personnalisable depuis le terminal ;

  • Permettre à nos collègues d’utiliser ce script même en notre absence.  

Imaginons que vous êtes Machine Learning Engineer et que vous avez construit un modèle de recommandations de produits pour des clients d’un site d’e-commerce. Vous êtes responsable de la maintenance de l’algorithme et de la donnée qu’il utilise. Au fil de l’eau, vous vous êtes rendu compte qu’il fallait mettre en place des modèles de Machine Learning spécialisés par gamme de produits, afin de gagner en précision.

Voici un exemple de code d’une fonction main très simple. Une fois lancé via un terminal avec deux arguments (la gamme de produits en question et un flag qui permet d’afficher ou non plus de détail dans l’exécution du script), ce script va récupérer les arguments et charger le modèle approprié à la gamme, puis effectuer des prédictions avec de la nouvelle donnée.

from argparse import ArgumentParser
from models import (
load_model, # Imaginons que c'est un script fait à la main qui s'occupe de charger les modèles ML
model_inference # Idem, mais pour réaliser de l'inférence tout en affichant des informations
)
from data_processing import load_customer_prod_data # Idem, mais pour charger de la donnée nécessaire pour réaliser les prédictions
parser = ArgumentParser("On selectionne le modele en fonction de la gamme de produit")
parser.add_argument("--gamme")
parser.add_argument("--verbose")
def main(argv):
args = parser.parse_args(argv) # Le script recupere les arguments specifies dans le terminal
modele_gamme = load_model(args["gamme"]) # On cherche le modele correspondant a la gamme donnee en argument
gamme_customer_data = load_customer_prod_data(args["gamme"]) # Idem pour la donnee
model_inference(model_gamme, gamme_customer_data, args["verbose]) # On lance l'inference en precisant avec l'argement verbose si on souhaite afficher plus d'informations
if __name__ = "__main__":
main() # Necessaire pour pouvoir lancer la fonction precedente depuis le terminal

Nous écrivons ce code dans un script  inference_main.py  que nous plaçons dans un dossier  src  (c’est la pratique conventionnelle !), au sein de notre dossier projet qui contient déjà notre fameux  pyproject.toml  et notre  poetry.lock  .

On peut lancer via notre Terminal/PowerShell notre script d’inference au sein de l’environnement virtuel avec les commandes suivantes :

poetry shell
python src/inference_main.py —gamme=gamme_3 —verbose=True

Mais on peut également combiner les deux commandes précédentes en une seule.

poetry run python src/inference_main.py —gamme=gamme_3 —verbose=True

La commande précédente va lancer l’environnement virtuel, lancer le script, puis sortir de l’environnement ! Comme vous pouvez le voir : de la même manière que vous pouvez donner des arguments à un script dans votre terminal pour afficher des informations supplémentaires ou lancer des bouts de code spécifiques, on peut préciser ces mêmes arguments avec  poetry run  .

Si c’est un script que l’on va être amené à utiliser plusieurs fois (ce qui est typiquement le cas de notre exemple fictif), on peut aller un cran plus loin et capitaliser sur une autre fonctionnalité de Poetry : la mise à disposition d’entrypoints.

Pour cela, on ouvre notre cher fichier  pyproject.toml  et on y rajoute la section suivante en créant un alias pour votre script d’inference :

[tool.poetry.scripts]
inference_par_gamme= ‘src.inference_main:main’

Ce qui vous permet d’exécuter votre même script sans avoir à le chercher dans le dossier  src  :

poetry run inference_par_gamme —gamme=”gamme_3” —verbose=True 

J’ai l’impression que tu n’as utilisé ces “entrypoints“ que pour faire du renommage… Y a-t-il une autre utilité aux entrypoints ?

Tout à fait ! Le vrai objectif des entrypoints est de permettre à des fonctionnalités clés de votre projet d’être utilisées par d’autres systèmes.

Reprenons notre cas d’usage de tout à l’heure : vous partez en vacances pendant 3 semaines, et un autre Machine Learning Engineer de votre équipe “est de garde” pour la maintenance du projet, sauf qu’il le connaît significativement moins bien que vous ! Plus particulièrement, il ne sait pas quel autre système/logiciel utilise votre code (Une API ? des pipelines GitHub Actions ? etc.)

Eh bien pas de panique, vous avez déjà préparé le terrain en amont et vous avez défini en tant qu’entrypoints toutes les fonctionnalités clés de votre projet de Machine Learning :

  • Un entrypoint pour rafraîchir la donnée utilisée pour un réentrainement éventuel du modèle de Machine Learning

  • Un entrypoint pour réentraîner le modèle de Machine Learning si besoin

  • Un entrypoint pour demander au modèle de réaliser des prédictions sur la donnée la plus récente (c’est l’entrypoint de tout à l’heure)

En réalité, tout script qui peut être lancé via un terminal peut être défini en tant qu’entrypoint dans le  pyproject.toml  !

La majorité des outils/softwares de votre équipe Dev/Data vont utiliser le code de votre projet en allant directement chercher les entrypoints et les exécuter. Ce sont des composantes nécessairement plus critiques et visibles que le reste de votre code.

Il sera plus facile pour votre collègue de prendre la relève temporairement en connaissant ces éléments, plutôt que d’encaisser toute la documentation technique ainsi que les milliers de lignes de codes (si ce n’est plus)

Configurez votre environnement de travail et vos packages

Quand vous déclarez un nouvel environnement avec  poetry init  , vous avez peut-être remarqué qu’on vous demande de définir vos dépendances deux fois : d’abord vos dépendances principales (main dependencies) puis vos dépendances de développement (development dependencies).

De quoi s’agit-il ?

Nous avons délibérément omis lors du chapitre précédent cet aspect lors de la partie Installation, pour rester simple. Maintenant, nous allons nous y intéresser, car il s’agit d’une fonctionnalité assez pratique de Poetry !

Imaginons que vous êtes Data Engineer et que vous devez récupérer des données brutes disponibles via une API afin de les transformer en un format cible.

  • Vous allez peut-être prototyper un script Python pour requêter l’API et consolider ces résultats, puis réaliser des transformations de données avec le package Polars par exemple. 

  • Enfin, vous voulez stocker les données traitées dans une base de données avec laquelle vous communiquez via le package SQLAlchemy.

  • Pour des premiers tests, vous avez utilisé Jupyter Notebook, vous poussez votre code dans un repo GitHub et vous utilisez également pre-commit pour garder votre code propre pendant vos commits au repo.

Parmi l’ensemble des packages cités :

  • Certains sont indispensables pour le fonctionnement du projet sur le fond : Interrogation de l’API, Polars, SQLAlchemy.

  • D'autres sont utiles pour vous en tant que développeur pour être plus productif ou adopter des bonnes pratiques de code : Juypter Notebook, pre-commit.

Ceci est important, car quand vous voulez exécuter votre projet en production, vous avez tout intérêt à l’exécuter dans un environnement virtuel le plus léger possible. Inutile de s'encombrer alors avec des dépendances superflues pour le fonctionnement du code sur le fond, comme Jupyter !

Vous pouvez implémenter cette distinction quand vous installez un nouveau package en utilisant l’option suivante, qui précise qu’il s’agit d’une dépendance de dev et non principale.

poetry add jupyter—group dev

La distinction est immédiatement visible au sein du fichier  pyproject.toml  , où l’on trouve deux catégories distinctes de packages :

[tool.poetry.dependencies]
polars= "^1.0.0"
sqlalchemy=”^1.4.22”
[tool.poetry.dev-dependencies]
jupyter= "^1.0.0
pre-commit = “^3.7.1”

Enfin, pour installer uniquement les dépendances principales dans votre environnement de production, vous pouvez utiliser :

poetry install —without dev 

Partagez votre travail avec Poetry

On a évoqué tout à l’heure les entrypoints comme une fonctionnalité intéressante pour que d’autres systèmes puissent utiliser certaines briques clés de votre code de manière automatisée.

Mais si un autre développeur veut utiliser votre code pour construire son projet, en se servant de fonctionnalités non-déclarées en tant qu’entrypoints, comment fait-on ?

Il suffit qu’il aille sur mon repository git puis un git pull ou un git fork non ?

Techniquement oui, mais ce ne serait pas pratique du tout ! C’est comme dire que pour commencer mon projet Data, il faudrait que j'aille faire un git pull du repository de Pandas, et partir de celui-ci pour construire mon code ! Ça n’aurait aucun sens, à moins que votre projet consiste à proposer une amélioration ou une variante de Pandas !

Dans notre cas, l’option la plus simple serait de transformer le code de notre projet en package ! Eh oui ! Cela signifie que d’autres développeurs pourront installer votre projet en tant que dépendance, comme vous le ferez avec  pip install  (ou désormais  poetry add  ;) ) avec Numpy ou autre package connu ! 

Heureusement, Poetry nous facilite énormément ce travail, car nous pouvons utiliser la commande :  poetry build  .

Cette simple ligne de code va réaliser plusieurs opérations sous le capot pour générer un fichier  wheel (.whl)  . Pour faire simple :

  • Un fichier  .whl  est une archive contenant votre code source Python, ainsi que le code compilé de toutes les sous-dépendances hors Python que vous utilisez (par exemple, le package Numpy propose des calculs en langage C, beaucoup plus rapide ;)).

  • Pour partager votre package avec la communauté, vous pouvez utiliser la commande poetry publish qui va rendre votre fichier  .whl  disponible dans PyPi, le répertoire de tous les packages Python !

  • Installer un package avec Pip ou Poetry revient à demander à ces outils de chercher le fichier  .whl  du projet dans PyPi, et de l’installer. Ceci vous permet d’utiliser son code.

En entreprise, mettre à disposition du code projet sous format  .whl  est une pratique très utile quand vous construisez un package qui a vocation à être utilisé par plusieurs équipes. Par exemple, vous êtes Data Engineer et vous avez investi beaucoup de temps et d’efforts à créer des pipelines pour consolider des données brutes sous un format utilisable par des Data Analysts, Data Scientists et Analytics Engineers. En plus, vous savez que vos collègues travaillent principalement en Python. Vous leur facilitez alors énormément la vie en créant un package avec  poetry build  qu’ils peuvent installer pour travailler directement avec vos pipelines et vos données consolidées.

Ceci nous amène à parler du minimum syndical à faire pour partager votre projet. Pour simplifier les choses, nous avons sauté quelques étapes dans le chapitre précédent quand nous avions lancé  poetry init  pour la première fois. En effet, nous avions grillé les étapes liées à l’auteur, la description et surtout la licence.

En outre, prendre la décision de partager votre travail en tant que package vous impose également d’adopter le maximum possible de bonnes pratiques de programmation, afin de ne pas donner envie aux utilisateurs de votre package de s’arracher les cheveux à débugger votre code. En revanche, rentrer dans le détail de ces bonnes pratiques dépasserait largement le périmètre de ce chapitre.

En résumé

  • Les entrypoints permettent à d'autres applications/softwares d'exécuter via l'environnement Poetry des scripts de votre projet.

  • L'environnement virtuel peut être personnalisé en définissant des groupes de dépendances au sein du fichier  pyproject.toml 

  • Poetry permet de facilement packager votre code projet en un format  .whl  facile à installer par vos collègues. 

  • Vous pouvez publier votre code en tant que package sur PyPi afin que la communauté des développeurs Python puisse s'en servir.

Vous voici parvenu aux termes de ce cours ! Félicitations ! Avant de nous quitter, je vous invite à tester vos connaissances dans le quiz final !

Exemple de certificat de réussite
Exemple de certificat de réussite