Les environnements virtuels Python : venv, virtualenv et virtualenvwrapper

Quand on commence à beaucoup programmer, on accumule rapidement plusieurs projets en cours de développement sur sa machine. Certains vieux, certains récents, qui utilisent tous des bibliothèques similaires, mais pas forcément de mêmes versions. Ou parfois des bibliothèques incompatibles. Parfois même, des version différentes de Python: Python 2.6, 2.7, 3.2 ? Et c’est sans compter les mises à jour de l’OS, qui a ses propres besoins en terme de libs et de versions.
Le jour où ça casse, c’est le chaos.
Dans le monde de Python, la solution à ce problème est d’utiliser des environnements virtuels. Ça à l’air d’un gros mot, mais derrière ce terme se cache la notion simple d’avoir des installations de Python isolées de l’OS, et séparées les unes des autres pour chaque projet.
Il existe plusieurs écoles: certains utilisent buildout. C’est une solution puissante, et très compliquée. Python 3.3 vient avec venv, un outil intégré pour gérer les environnements virtuels, qui peut être installé séparément sur les versions plus anciennes sous le nom de virtualenv.

Installation et usage

Vérifiez si vous avez virtualenv déjà installé:

$ python -m venv
usage: venv [-h] [--system-site-packages] [--symlinks | --copies] [--clear]
            [--upgrade] [--without-pip]
            ENV_DIR [ENV_DIR ...]
venv: error: the following arguments are required: ENV_DIR

Si cette commande ne marche pas, il faudra installer virtualenv:

pip install --user virtualenv

Si vous avez besoin d’un rappel sur pip, c’est par là.
Ensuite, pour chacun de vos projets, créez un environnement virtuel, avec:

python -m venv /path/vers/projet/env_nom_du_projet

Si vous l’aviez déjà. Ou:

virtualenv /path/vers/projet/env_nom_du_projet

Si vous venez de l’installer. Les deux commandes sont interchangeables.
Virtualenv va créer un dossier avec un environnement complet dedans: l’interpreteur Python, les libs, des commandes, etc. C’est votre installation isolée.
Pour travailler dans votre installation isolée:

  • sous Unix, il faut faire source /path/vers/projet/env_nom_du_projet/bin/activate.
  • sous Windows, il faut faire C:\\path\vers\projet\env_nom_du_projet\Scripts\activate.bat.

Votre prompt de ligne de commande va changer pour indiquer que vous êtes dans un environnement virtuel:

(env_nom_du_projet) sam $

Si vous installez une bibliothèque avec pip, il l’installera dans cet environnement virtuel, et elle ne sera pas accessible ailleurs. Si vous lancez la commande python, le shell Python aura accès à toutes les libs de cet environnement virtuel.
Vous pouvez sortir de l’environnement virtuel avec la commande deactivate.
Créez autant de virtualenv que vous voulez: un par projet, un pour les tests de nouvelles libs, un pour le plaisir, un pour la route… Ça prend juste de la place, et ce n’est pas ce qui manque sur nos disques durs de nos jours.

Quelques astuces avec virtualenv

Isolation par rapport à l’OS

Vous pouvez choisir que votre env hérite des libs de l’OS, ou non, mais uniquement à la création. Il faut spécifier une option:

  • --no-site-packages: votre environnement est vierge, il n’hérite pas des libs du système et a seulement accès aux libs standards de Python (os, sys, itertools, json, etc).
  • --system-site-packages: tout ce qui est installé sur l’OS est disponible dans installé dans l’env (et sera installé à l’avenir). Par exemple sous Ubuntu, vous pourrez importer toutes les libs d’UbuntuOne, le système de synchronisation Cloud d’Ubuntu écrit en Python.

Les anciennes versions ont la valeur --system-site-packages activée par défaut, les nouvelles versions de virtualenv ont la valeur --no-site-packages activée par défaut.
Si vous utilisez --system-site-packages, vous pouvez quand même demander à pip freeze de lister uniquement les libs de l’env avec l’option --local.

Choisir une version de Python

Parfois vous voudrez utiliser une version spécifique de Python. Vous pouvez tout à fait créer un env dédié à Python 3.2 et un autre à Python 2.6, il faut juste que les deux versions soient installées sur votre système.
Je ne vais pas détailler comment installer deux versions de Python en parallèle sur chaque OS car je n’ai aucune idée de comment on fait sous Mac ou Windows, mais sous Ubuntu c’est très simple: par défaut on est en Python 2.7, et pour installer Python 3, on fait sudo apt-get install python3. Pour installer Python 2.6, on fait sudo apt-get python2.6.
On a alors 3 exécutables: /usr/bin/python va déclencher Python 2.7, /usr/bin/python2.6 va appeler Python 2.6, etc. Aucun conflit système, c’est merveilleux.
Il ne reste qu’à construire son environnement virtuel en lui passant en paramètre le chemin vers le Python à utiliser:

virtualenv mon_env -p /usr/bin/python2.6

Et voilà, si on active « mon_env », la commande python ouvre un shell en Python 2.6, et toutes les libs de l’env sont en 2.6.
Attention: on ne peut pas reconvertir facilement un env d’une version de Python à l’autre. Une fois que c’est créé, c’est fait. Si vous changez d’avis, faite un pip freeze, supprimez l’env, recréez l’env, et faites un pip install -r.

Virtualenv depuis un script extérieur

Si vous êtes dans un script extérieur et que vous voulez appeler un de vos scripts avec ce virtualenv, vous n’avez pas besoin de l’activer pour que ça marche. Il suffit d’appeler le script en le passant en paramètre à l’interpréteur de l’env. Par exemple:

/path/vers/projet/env_nom_du_projet/bin/python mon_script.py

Le script sera alors exécuté dans le cadre du virtualenv.

virtualenvwrapper: ou comment ne pas s’embêter pour passer d’un env à l’autre

Si vous êtes sous Windows, vous pouvez aller boire une bière à la cuisine, ça ne marche pas sous votre OS.
Pour les chanceux qui ont accès à un Unix, il existe un merveilleux logiciel qui va vous éviter le yoyo entre les envs:

pip install --user virtualenvwrapper

Ensuite il faut rajouter quelques lignes dans votre script d’init de shell, par exemple dans ~/.bashrc:

export WORKON_HOME=~/.virtualenvs
mkdir -p $WORKON_HOME
source ~/.local/bin/virtualenvwrapper.sh

Selon où vous avez installé virtualenvwrapper, la dernière ligne peut changer. Moi, mon virtualenv est installé au niveau du système dont le chemin est plutôt /usr/local/bin/virtualenvwrapper.sh.
Ces lignes vont lancer virtualenvwrapper en permanence dans le shell. Relancez le terminal pour l’activer. Le premier lancement va vous afficher un tas de lignes, rassurez-vous, ça n’arrive qu’une fois.
Ensuite, vous avez accès à de nouvelles commandes:

  • mkvirtualenv nom_env va créer un virtualenv dans le dossier ~/.virtualenvs, où que vous soyez.
  • workon nom_env va automatiquement activer un env, où que vous soyez.
  • rmvirtualenv nom_env va surpprimer l’env du même nom.

Les options de mkvirtualenv sont les mêmes que pour la commande virtualenv, vous n’avez juste plus à vous souciez de où sont vos envs, ni de où vous êtes.