💬 « - Python c’est installé. J’ai un package manager. J’ai un gestionnaire d’environnements virtuels et j’ai twine pour publier mes packages. »
C’est fastidieux, non ?
Si vous avez répondu oui, vous êtes tombé·e au bon endroit, j’ai une solution pour vous. Si vous avez répondu non, vous êtes également au bon endroit, vous n’avez juste pas encore compris à quel point vous avez besoin d’un outil pour faire tout ça.
Bienvenue sur le blog de Coddity et ensemble on va parler de poetry, un outil très complet qui va vous permettre d’installer les librairies nécessaires à votre projet Python, tout en gérant les dépendances mieux que pip, d’avoir à disposition des environnements virtuels sans avoir à les créer explicitement à la main et de publier plus facilement vos packages sur un repo distant.

1. Gestion des dépendances

pip install -r requirments.txt
[...]
ERROR: aiobotocore 1.4.2 has requirement botocore<1.20.107,>=1.20.106, but you'll have botocore 1.24.24 which is incompatible.
Ca vous parle ? Mais pourquoi diable nous laisse-t-il installer des librairies incompatibles entre-elles ? Avec poetry, ça n'arriverait pas car il ne vous laissera pas faire. Finis donc les risques de problèmes inattendus parce que malgré l’incompatibilité, les librairies se sont installées quand même.
Globalement, l’idée est la même qu’avec pip : un fichier à remplir (qui s'appelle pyproject.toml) avec les librairies à installer et les versions précisées si une version spécifique est nécessaire (c’est souvent conseillé pour éviter des problèmes liés à des évolutions dans les librairies qui créeraient des incompatibilités).
Ensuite, avec la commande poetry install, les librairies s’installent ainsi que votre projet en lui-même).
Quelques subtilités cependant :
  • Il y a une section pour les dev-dependencies que vous pourrez choisir de ne pas installer avec l’argument --no-dev. Et vous pouvez ajouter de nouvelles librairies avec la commande poetry add qui installera la librairie tout en l’ajoutant au pyproject.toml.
  • Le projet est installé par défaut en lui-même (là où avec pip, il est nécessaire de lancer pip install .). Si vous souhaitez ne pas l'installer, ajoutez la commande --no-root.
On verra le détail du fichier pyproject.toml par la suite (mon employeur me rémunère en fonction du temps que vous passez sur cet article et j’ai vu un très beau canapé chez Ikea donc je vous tiens en haleine).

2. Les environnements virtuels

C’est la feature qui m’enjaille le plus. A titre personnel, j’utilisais virtualenvwrapper et je créais systématiquement mes environnements virtuels manuellement pour chaque projet en faisant mkvirtualenv -a . projet avec éventuellement différentes versions de Python à préciser dans la commande, bref.
Avec poetry vous avez un envrionnement virtuel directement sans écrire aucune commande. En effet, poetry install n’installera pas les librairies pour l’utilisateur·rice de votre machine, vous pouvez vérifier avec un pip freeze. Elles sont dans un environnement dans lequel vous pouvez vous placer avec la commande poetry shell. Sinon, pour lancer des commandes dans le shell de l’environnement virtuel depuis votre machine directement, il faut faire poetry run <commande>.
Par exemple :
$ poetry run python --version
Python 3.8.10
L’avantage de ne pas avoir à créer les environnements virtuels à la main c’est le gain de temps, mais c’est assez léger. Pour moi, le vrai gain c’est que quand poetry est mis en place sur un projet, il y a beaucoup moins de risque d’avoir des collègues pour qui le code fonctionne alors que vous non ou inversement parce que lae dit·e collègue n’a pas d’environnement virtuel/n’a pas fait attention et dispose/ne dispose pas de paquets dont vous disposez. Grâce à poetry, tout le monde dipose de l'environnement virtuel sans avoir rien fait de spécial.

3. Publication de son package

Cette section pourrait tenir en une ligne mais il y avait aussi un bureau que j’avais vu chez Ikea. Promis on va voir à quoi ressemble le pyproject.toml et comment mettre ça en place juste après. Laissez-moi convaincre les dernier·ère·s sceptiques.
Pour publier un package en Python on installe twine, on build son package et on le publie. Imaginez qu’il suffise de faire poetry publish. Eh bien si, je vous jure, poetry embarque une commande qui permet de publier son package sur un repo directement. Il suffit de fournir à la commande le repository, le nom d’utilisateur·rice et le mot de passe et c’est tout. Allez, écrivez après moi : pip uninstall twine.

4. « Bon alors comment ça se passe pour adopter poetry ? »

Pour installer poetry, je ne vais pas recopier ce qui est déjà sur la doc et puis si ça évolue au moins vous serez à jour, je vous invite à aller ici : https://python-poetry.org/docs/ et suivre la procédure indiquée.
Fin du suspens, le fichier pyproject.toml ressemble à ceci :
[tool.poetry]
name = "mon-projet"
version = "13.12.0"
description = "Mon projet super cool que je package avec poetry"
authors = ["Prénom Nom <prenom.nom@mail.com>"]

[tool.poetry.dependencies]
python = "^3.8"
python-dateutil = "^2.8.2"
pandas = "^1.3.3"
requests = "^2.25.1"
python-twitter = "^3.5"

[tool.poetry.dev-dependencies]
pytest = "^7.1.1"
ipdb = "^0.13.9"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Pas de panique il se génère automatiquement avec la commande poetry init si vous êtes déjà dans un projet. Sinon vous pouvez commencer à démarrer vos projets Python avec poetry new.
Ce fichier est un peu une manière de regrouper les fichiers qu'on retrouve classiquement dans les projets Python, à savoir : le setup.py, le setup.cfg et le requirements.txt.
  • La première section [tool.poetry] recense des informations sur votre projet. On y trouve le nom du projet, sa version, une description et la liste de ses auteur·rice·s.
  • La seconde section [tool.poetry.dependencie] recense les libraires nécessaires à votre projet.
  • La troisième section [tool.poetry.dev-dependencies] ce sont les dépendences utiles aux développeur·euse·s du projet.
  • Et la quatrième section [build-system] aide poetry à installer votre projet.
Vous pouvez ajouter ou retirer manuellement les librairies et ensuite utiliser pip install pour prendre en compte les changements mais le mieux c’est d’utiliser les commandes prévues à cet effet poetry add et poetry remove.
Exemple de poetry add :
$ poetry add python-twitter

Using version ^3.5 for python-twitter

Updating dependencies
Resolving dependencies... (0.2s)

Writing lock file

Package operations: 4 installs, 0 updates, 0 removals

  • Installing oauthlib (3.2.0)
  • Installing future (0.18.2)
  • Installing requests-oauthlib (1.3.1)
  • Installing python-twitter (3.5)
👉 Le package python-twitter et toutes ses dépendances sont installé·e·s.

5. Lister les packages installés

Une dernière commande avant de se quitter. Pour voir vos packages avec pip vous utilisiez pip freeze ou pip list.
Avec poetry, la commande est poetry show et il y a même un affichage amélioré qui fait un graphe avec les dépendances en ajoutant l'argument --tree.
Voici un extrait d'un poetry show --tree :
pytest 7.1.1 pytest: simple powerful testing with Python
├── atomicwrites >=1.0
├── attrs >=19.2.0
├── colorama *
├── iniconfig *
├── packaging *
│   └── pyparsing >=2.0.2,<3.0.5 || >3.0.5
├── pluggy >=0.12,<2.0
├── py >=1.8.2
└── tomli >=1.0.0
python-dateutil 2.8.2 Extensions to the standard Python datetime module
└── six >=1.5
python-twitter 3.5 A Python wrapper around the Twitter API
├── future *
├── requests *
│   ├── certifi >=2017.4.17
│   ├── chardet >=3.0.2,<5
│   ├── idna >=2.5,<3
│   └── urllib3 >=1.21.1,<1.27
└── requests-oauthlib *
    ├── oauthlib >=3.0.0
    └── requests >=2.0.0
        ├── certifi >=2017.4.17
        ├── chardet >=3.0.2,<5
        ├── idna >=2.5,<3
        └── urllib3 >=1.21.1,<1.27


Voilà pour les principaux aspects qui ont retenu mon attention et les principales commandes (il y en a d’autres mais si j’avais fait la liste complète j’aurais pu acheter l’entièreté d’Ikea, or je suis dans une démarche minimaliste). Pour en consulter la liste : poetry help

Ressources :

La doc de poetry : https://python-poetry.org/
fin