Gérer ses environnements virtuels Python

But du jeu

Dans un article précédent,
Léo nous expliquait comment isoler ses projets Python pour éviter
les conflits de dépendances : utiliser des environnements virtuels.

Et il a parfaitement raison. Les environnement virtuels
(ou venv pour Virtual ENVironment), c’est bon, mangez-en à tous les repas.
Un projet Python ? Un venv. Essayer une nouvelle lib vite fait ? Un venv.
Tester le code d’un collègue ? Un venv. Venv, venv, venv, pas une ligne
de Python qui ne soit développée dans un venv.

Mais au bout d’un moment ça commence à devenir un peu le bazar,
tous ces venv. En plus, le chemin du venv n’est pas normalisé.
Il est parfois situé directement dans le projet, dans le dossier
venv, mais parfois c’est .venv (avec un point). Mais dans
ce cas les fichiers du venv peuvent polluer l’IDE ou la recherche de mot clé
(un grep ou sa version vitaminée ack).
Mais alors où est le venv s’il n’est pas dans le projet ?

Niveau 1: pew

pew est un gestionnaire de venv. Comme il est écrit en Python,
il s’installe tout simplement avec pip:

pip install pew
# pip3 install pew sur les distributions Debian-like

Et on lui délègue tout ce qui a trait aux environnement virtuels.

Un nouveau venv ?

pew new mon-nouveau-venv

pew lance alors un sous-terminal tout en entrant dans le venv.
Plus besoin de deactivate, un Ctrl+D ou un exit suffisent.

Entrer dans un venv existant ?

pew workon mon-super-venv

J’ai oublié mon (mes) venv ?

pew ls

Mais il est où le venv finalement ?

pew dir mon-venv-perdu

Et évidemment on peut supprimer, renommer, copier… les venv,
et beaucoup de choses encore. Dernier point très utile,
lancer une commande à l’intérieur du venv:

pew in mon-autre-venv ma-commande

Et si j’ai oublié les commandes pew elles-mêmes ? Et bien juste :

pew

Tout simplement.

Niveau 2: pipenv et poetry

C’est pas tout de gérer les venv, les dépendances restent un problème
même à l’intérieur d’un projet. Bien sûr, on peut faire un requirements.txt,
mais les dépendances des dépendances ne seront pas dedans. Alors on peut
créer le requirements.txt avec pip freeze, mais pip freeze donne
l’état actuel du venv, y compris les paquets potentiellement en trop.
Et bonjour pour faire le tri. En plus, pip ne vérifie pas que les
dépendances de nos dépendances sont toutes compatibles : on peut installer
un paquet qui casse un paquet déjà installé.

Entre alors en jeu une nouvelle génération d’outils, des gestionnaires de projet
tout en 1, qui font tout ce que fait pew et encore plus. Ici nous en verrons deux :
pipenv
et poetry. pipenv peut s’installer pip ou pipx
(voir plus bas), poetry a son propre installeur.

Le principe est le même : un venv est créé à la racine du projet (en général
la racine du dépôt git), et il est géré par l’outil (pipenv utilises
d’ailleurs pew pour ça en interne). Et les dépendances sont gérées aussi :
plus de pip install, mais:

pipenv install mon-paquet

ou

poetry add mon-paquet

L’outil cherche alors une version compatible du paquet et de toutes
ses dépendances avec les dépendances existantes et leurs contraintes.

Le paquet est alors inscrit dans 2 fichiers. Dans un premier fichier
« lisible » (Pipfile pour pipenv, pyproject.tom pour poetry),
les paquets directement requis par l’utilisateur sont écrits avec
leurs éventuelles contraintes (version minimale, maximale, figée,
version de Python…) et selon 2 catégories : production (par défaut)
ou développement (quand on utilises l’option --dev).

Dans un second fichier (Pipfile.lock ou poetry.lock), on trouve la liste de toutes
les dépendances, y compris indirectes, avec leur version et leur hash.
Ainsi, on installant le projet à partir du fichier *.lock,
la reproductibilité est assurée.

Par exemple, pour des tests automatiques (en CI), on pourra
reproduire l’environnement à l’identique et lancer les tests dans la foulée:

pipenv install
pipenv run pytest

ou

poetry install
poetry run pytest

À bien des égards, ces deux outils sont très semblables.
Les deux ont une bonne documentation, s’intègrent facilement aux IDE,
ont une interface claire et pratique,
et font des tonnes de trucs que je ne peux pas détailler ici.
Alors pourquoi deux ?

D’abord, pipenv a un périmètre restreint au développement d’applications,
alors que poetry peut aussi servir à développer des libraries. En effet,
poetry possède en plus des commandes pour empaqueter et publier son projet.
Même plus besoin de faire son setup.py.

Ensuite, le développement de pipenv, qui avait démarré sur les chapeaux de roues,
a été bloqué par des conflits pendant un bon moment, gelant les bugs et les retours
d’utilisateurs. Ce qui a motivé l’auteur de poetry, et lui a permis d’orienter
différemment l’interface et de faire l’empaquetage.

Au final, pour une application, autant prendre celui dont on préfère l’interface.

Bonus

Les venv permettent d’isoler les projets en développement les uns des autres, mais
qu’est-ce qui se passe pour les outils Python installés avec pip ? pew, pipenv
et poetry par exemple, on ne peut pas les mettre dans un venv puisqu’ils servent à les
gérer ! Et si je veux tester pew et pipenv, mais que pipenv utilise pew comme
dépendance, il n’y pas un risque de conflit ?

Évidemment il y a une solution : pipx. En effet, pipx installe les applications
comme pip tout en les encapsulant dans des environnements virtuels. À l’usage,
la différence avec pip est seulement un petit ‘x’, mais ça garantit que les
applications installées au niveau du système sont isolées.

Par Jonathan Gaffiot