Poetry + Conda + Fish : Le meilleur environnement pour les développeurs python ?

David Toussaint
MoveNext
Published in
8 min readJan 23, 2024

Introduction

La gestion efficace des environnements et des dépendances est un pilier crucial pour les développeurs Python, permettant de maximiser la productivité et de minimiser les tracas techniques. Dans cet écosystème, plusieurs outils se distinguent par leur capacité à résoudre divers problèmes:

  • Conda : Ce gestionnaire d’environnement et de packages se spécialise dans la création d’environnements Python isolés, permettant une coexistence harmonieuse de multiples projets avec des besoins différents. Sa capacité à intégrer des packages non-Python est particulièrement appréciée.
  • Poetry : En se concentrant sur la gestion des dépendances et le packaging, Poetry offre une approche simplifiée et élégante pour maintenir l’intégrité des projets Python. Sa facilité d’utilisation et son système de résolution de dépendances précis facilitent grandement le cycle de vie du développement.
  • Conda Pack : Cet outil complète Conda en facilitant le packaging et le transfert d’environnements Conda, permettant ainsi une portabilité et une reproductibilité accrues des environnements de développement et de production.
  • Fish (optionnel) : Est un shell amélioré pour système Unix, que nous allons utiliser pour rendre la gestion des environnements plus intuitive.

L’intégration harmonieuse de ces outils peut créer un écosystème de développement Python extrêmement puissant, capable de résoudre efficacement une large gamme de problèmes liés à la gestion d’environnements, à la gestion des dépendances, au packaging, et à la facilité d’utilisation. Cette combinaison pourrait-elle être la clé pour un environnement de développement Python optimisé ? Nous allons explorer cette question à travers cet article.

Je passe les détails de l’installation de Poetry, Conda et Fish dans cet article, car ces informations sont facilement disponibles dans les documentations officielles.

Gestionnaire d’environnement — Conda :

Dans le vaste monde de la gestion d’environnements virtuels Python, Conda (et ses cousins) se distingue souvent comme un choix privilégié. Voici pourquoi je me tourne régulièrement vers Conda pour mes projets :

  1. Conda excelle dans la création d’environnements isolés pour des versions spécifiques de Python, permettant ainsi une gestion précise et flexible des projets.
  2. Contrairement à PyPI, qui est exclusivement dédié aux packages Python, le référentiel de Conda est plus étendu. Il permet d’installer des dépendances allant au-delà de l’écosystème Python, ce qui est un avantage considérable pour les projets nécessitant des librairies complexes ou inter-langages.

Cependant, il y a des inconvénients à considérer :

  • Tous les packages présents sur PyPI ne sont pas forcément disponibles sur Anaconda, et inversement. Cette limitation peut être un obstacle, notamment si un projet dépend de packages spécifiques uniquement disponibles sur PyPI.
  • Bien qu’il soit techniquement possible de combiner Conda et Pip dans le même environnement, cette pratique peut conduire à des problèmes de gestion de packages. Lorsque Pip est utilisé pour installer des packages, il se charge également de leurs dépendances. Cependant, en cas de désinstallation, ni Anaconda ni Pip ne suppriment ces dépendances, laissant ainsi des résidus inutiles dans l’environnement. Cette accumulation de dépendances non désirées peut devenir problématique, en particulier lors du partage d’environnements au sein d’une équipe.

En conclusion, Conda s’avère être un excellent gestionnaire d’environnement pour Python, mais il présente certaines limitations en tant que gestionnaire de packages. Cela nous amène à considérer un autre outil important dans ce domaine : Poetry.

Gestionnaire de packages et de dépendances — Poetry :

Il existe une variété de gestionnaires de packages pour Python tels que PDM, Rye, Hatch, Flit, etc., mon expérience m’a principalement conduit vers Poetry. Voici pourquoi je trouve Poetry particulièrement efficace :

  1. Clarté dans la gestion des dépendances : Poetry se distingue par sa capacité à gérer les dépendances de manière transparente. Lorsqu’il rencontre un problème de dépendance, il le résout efficacement ou, à défaut, génère rapidement un message d’erreur explicite. Cette clarté contraste avec d’autres outils qui peuvent soit masquer des problèmes sous-jacents, soit rester bloqués en tentant de résoudre des conflits de dépendances.
  2. Utilisation de sources de packages variées : Poetry s’appuie sur les sources de packages que vous choisissez, avec PyPI comme source par défaut. Cette flexibilité facilite la gestion des dépendances dans des contextes variés, y compris avec des dépôts privés.
  3. Reproductibilité : En fixant les versions des dépendances, le fichier poetry.lock, clé de voûte de poetry, garantit que le projet peut être reconstruit de manière identique dans divers environnements et à différents moments.
  4. Optimisation de l’installation : L’utilisation de poetry.lock lors de l’exécution de poetry install accélère le processus en éliminant le besoin de résoudre les dépendances à chaque installation.
  5. Amélioration de la sécurité : En verrouillant les versions des dépendances, Poetry aide à prévenir l’introduction accidentelle de versions plus récentes de packages qui pourraient comporter des vulnérabilités ou des bugs.

Poetry se révèle être un outil mature et fiable pour la gestion des packages et des dépendances, offrant à la fois clarté et contrôle dans la gestion des projets Python.

Un problème persiste : les dépendances non-Python

Bien que l’utilisation combinée de Conda et Poetry offre un environnement de développement robuste, il subsiste un défi notable :

  • Comme mentionné précédemment, Poetry se limite à la gestion des packages Python. Cependant, dans de nombreux projets, notamment en data science, des dépendances non-Python, telles que CUDA ou des bibliothèques pour l’OCR, sont souvent nécessaires. Dans ces cas, Poetry seul ne suffit pas, et Conda devient indispensable.
  • L’utilisation simultanée de conda install pour les dépendances non-Python et de poetry install pour les packages Python peut entraîner des conflits entre les systèmes de gestion de dépendances.

Une façon de faire :

  • Lors de l’initialisation de votre environnement Anaconda, il est conseillé d’installer d’abord les dépendances non-Python spécifiques à votre projet. Considérez ces dépendances comme des prérequis de votre environnement.
  • Si le besoin d’un package non-Python se fait sentir en cours de développement, la solution consiste à recréer l’environnement Anaconda en installant ces nouveaux packages via conda install. Ensuite, exécutez poetry install pour réintégrer les dépendances Python, en vous basant sur votre fichier poetry.lock ou pyproject.toml.

Cette approche, qui peut être confuse mais nécessaire au bon fonctionnement de la gestion de votre environnement et nécessite une attention particulière et doit être clairement communiquée au sein de l’équipe. Nous pouvons faciliter ce partage avec l’utilisation de Fish.

Facilité de gestion d’un environnement de Développement — Fish

Après avoir maîtrisé Conda et Poetry, et pris en compte les subtilités rencontrées pendant le développement, il est temps d'introduire Fish, un outil qui n’est pas indispensable mais peut simplifier la collaboration au sein de votre équipe.

Qu'est-ce que Fish ?

Fish, ou Friendly Interactive Shell, est un interpréteur de commandes disponible pour les systèmes Unix. En utilisant une des fonctionnalités de Fish, cela va nous faciliter l'interaction avec nos environnements de développement Python.

Une des fonctionnalités clés pour notre cas :

  • Fish vous permet d'avoir des fonctions personnalisées qui s'activent en fonction des événements dans votre shell. Par exemple, vous pouvez configurer une fonction qui s'exécute automatiquement lorsque vous naviguez entre les répertoires d'un projet.

Dans ma configuration Fish (~/.config/fish/config.fish), j'ai ajouté cette fonction :

function setup_project --on-variable PWD
set -l current_dir $PWD
while [ "$current_dir" != "/" ]
if test -d "$current_dir/.git"
if test -f "$current_dir/.fish"
source "$current_dir/.fish"
echo "use $current_dir/.fish"
break
end
end
set current_dir (dirname $current_dir)
end
end

Cette fonction vérifie si vous êtes dans un répertoire Git (ou sous-répertoire) et cherche un fichier .fish à la racine du projet Git. Si trouvé, il le source, étendant ainsi les fonctionnalités de Fish en fonction du répertoire de projet. Sympa non ?

Utilisation de Fish dans les Projets Python :

Dans le fichier .fish placé à la racine du répertoire Git, j'ajoute généralement des fonctions pour créer et installer des environnements. Par exemple, la fonction env_create crée un environnement Conda et initialise Poetry en précisant une version de Python. La fonction env_install, quant à elle, installe l'environnement à partir du fichier requirements.yml de Conda et des fichiers Poetry.

function env_create --argument py_version
set env_name (basename $PWD)
set requirements_file "requirements.yml"
if test -n "$py_version"
conda deactivate
conda create --no-default-packages --name $env_name -y -q python=$py_version
conda activate $env_name
echo "---> Installing pip"
conda install pip -y
echo "---> Installing conda-pack"
conda install conda-forge::conda-pack -y
echo "---> Installing poetry"
conda install conda-forge::poetry -y

for package in $argv[2..-1]
echo "---> Installing additional package: $package"
conda install $package -y
end

conda env export --no-builds | grep -v "^prefix: " > $requirements_file
conda env create -f $requirements_file -y
rm pyproject.toml
rm poetry.lock
poetry init -n
echo "Do you want to activate this environment now? [Y/n]: "
read -l user_choice
switch $user_choice
case Y '' y
echo "Environment $env_name activated."
case '*'
conda deactivate
echo "Environment not activated. You can activate it later by running 'env_activate'."
end
else
echo "Please specify a Python version. Usage: env_create <python_version>"
end
end

function env_install
set env_name (basename $PWD)
set requirements_file "requirements.yml"
conda deactivate
if test -f $requirements_file
echo "Installing packages from $requirements_file in the $env_name environment..."
conda env create -f $requirements_file
conda activate $env_name
poetry install --no-root
conda deactivate
echo "Installation complete."
else
echo "requirements.yml found in the current directory."
end
end

## Alias
alias ec='env_create'
alias ei='env_install'
  • Avec ces fonctions, vous pouvez créer et gérer des environnements en fonction du répertoire du projet, rendant le processus plus intuitif et facile à suivre.
  • La magie dans ses fonctions c’est que les noms des environnements sont définis par le nom du répertoire dans lequel vous vous trouvez. Cela facilite l'association rapide d'un environnement à un projet spécifique.
  • Le fichier .fish peut être commité dans votre répertoire Git, permettant à l'équipe de développement d'avoir une base commune de travail (à condition bien sûr que tous utilisent un système compatible avec Fish).

À vous d’imaginer toutes les autres fonctions qui vont faciliter votre vie et celle de votre équipe. Maintenant, passons au dernier point.

Création d’un package autonome et facilement distribuable avec Conda Pack :

Pour compléter notre arsenal d’outils de développement Python, il est pertinent de discuter de la distribution des packages. Bien que j’utilise souvent Docker pour cette tâche, il arrive que Docker ne soit pas une option viable. Dans ces cas, je me tourne vers Conda Pack, un outil que vous avez peut-être remarqué dans mes fonctions Fish.

  • Conda Pack est spécifiquement conçu pour packager des environnements Conda. Il crée un package autonome comprenant toutes les dépendances binaires et les bibliothèques nécessaires.
  • L’un des principaux avantages de Conda Pack est la facilité avec laquelle il permet de transférer des environnements Conda entre différentes machines. Cela facilite grandement la collaboration entre développeurs ou équipes, et se révèle particulièrement utile dans des situations où l’accès à Internet est limité ou pour assurer une cohérence entre les environnements de développement et de production.
  • Utiliser Conda Pack est généralement aussi simple qu’exécuter une commande pour packager un environnement et une autre pour le déployer ou le restaurer sur une nouvelle machine. Cela rend la distribution de votre environnement Python non seulement efficace mais aussi accessible

Bien que Poetry soit très bien dans la gestion et le packaging des dépendances Python, Conda Pack offre ces avantages supplémentaires lorsqu’il s’agit de créer des environnements Python complets et portables.

Conclusion :

Au fil de cet article, nous avons parcouru un paysage varié d’outils et de méthodes dédiés à la gestion d’environnements de développement Python. Bien que ma sélection d’outils et mon approche soient susceptibles d’évoluer avec le temps, je les considère actuellement comme un équilibre optimal.

Je suis conscient que je ne suis pas le seul à rechercher la clé d’un environnement Python à la fois cohérent, partageable et aisément accessible. C’est pourquoi je vous invite chaleureusement à partager vos expériences et vos propres solutions dans ce domaine. Vos contributions pourraient éclairer d’autres chemins et alternatives que nous n’avons pas encore explorés.

Je vous remercie pour votre lecture et j’attends avec impatience vos retours et suggestions. À bientôt pour de nouvelles découvertes ensemble !

references :
- https://medium.com/israeli-tech-radar/real-self-contained-python-environments-9aef0018f692
- https://docs.conda.io/projects/conda/en/stable/commands/index.html
- https://python-poetry.org/docs/basic-usage/£
- https://fishshell.com/
- https://conda.github.io/conda-pack/

--

--