Environnements virtuels

Le but d'un environnement virtuel est de créer un environnement python complet (interpréteur et modules) différent par projet. Ceci permet de contrôler les modules installés et utilisés.

Il est fortement recommandé de créer un environnement virtuel pour chaque projet.

Environnement python

On a vu que l'interpréteur python était un fichier sur notre ordinateur qui était exécuté pour interpréter du code, chacun pouvant avoir ses propres modules d'installés.

Emplacement

L'ensemble python et module est appelé environnement python et est placé dans un dossier. Le code suivant permet de l'expliciter :

import sys

print("environnement :", sys.prefix)

Ce qui donne chez moi (en 2024) le dossier /opt/homebrew/opt/python@3.13/Frameworks/Python.framework/Versions/3.13.

Testez le chez vous. Pour cela, créons un projet vscode qui nous permettra de tester tout ça.

  1. Créez un nouveau projet avec vscode que vous placerez dans un dossier nommé virt-python/.
  2. Créez un fichier main.py contenant le code :
import sys

print("environnement :", sys.prefix)

Vous pouvez exécuter le fichier main.py pour connaître le chemin vers l'interpréteur utilisé :

code exécution

Remarquez que :

En regardant cette arborescence avec la commande tree dans un terminal, on voit qu'elle contient un grand nombre de dossiers et de fichiers :

❯ tree -L 2 /opt/homebrew/opt/python@3.13/Frameworks/Python.framework/Versions/3.13 
/opt/homebrew/opt/python@3.13/Frameworks/Python.framework/Versions/3.13
├── Headers -> include/python3.13
├── Python
├── Resources
│   ├── Info.plist
│   └── Python.app
├── _CodeSignature
│   └── CodeResources
├── bin
│   ├── idle3 -> idle3.13
│   ├── idle3.13
│   ├── pip3
│   ├── pip3.13
│   ├── pydoc3 -> pydoc3.13
│   ├── pydoc3.13
│   ├── python3 -> python3.13
│   ├── python3-config -> python3.13-config
│   ├── python3.13
│   └── python3.13-config
├── etc
│   └── jupyter
├── include
│   └── python3.13
├── lib
│   ├── libpython3.13.dylib -> ../Python
│   ├── pkgconfig
│   └── python3.13
└── share
    ├── doc
    └── jupyter

16 directories, 14 files

Chaque dossier a sa propre fonction, citons-en deux :

Tous les modules ne sont pas présent dans le dossier lib/python3.13/. Par exemple math.py et sys.py ne s'y trouvent pas.

Les modules très souvent utilisés sont enb effet directement inclus dans l'interpréteur (bien qu'il faille tout de même les importer). Pour les voir, vous pouvez exécuter le code suivant :

import sys

for nom_module in sorted(sys.stdlib_module_names):
  print(nom_module)

Les petites flèches que vous voyiez à côté de certains noms, par exemple la ligne 17 précédente :

│   ├── python3 -> python3.13

Ceci correspond à un lien symbolique : le fichier python3 correspond en fait au fichier python3.13. Ce mécanisme permet de conserver un même nom (python3) à plusieurs versions python.

Si je change d'interpréteur (en cliquant sur la ligne en bas de vscode) :

Différents environnements

Vscode a trouvé plein d'environnements différents (et il ne les a pas trouvés tous). Si je change d'environnement et que je re-exécute le code :

code exécution autre environnement

Ce qui pourrait sembler être anecdotique est en fait crucial car les modules installés sont différents.

Packages installés pour l'environnement par défaut :

❯ /opt/homebrew/opt/python@3.13/Frameworks/Python.framework/Versions/3.13/bin/python3 -m pip list
Package                   Version
------------------------- --------------
anyio                     4.6.2.post1
appnope                   0.1.4
argon2-cffi               23.1.0
argon2-cffi-bindings      21.2.0
arrow                     1.3.0
asttokens                 2.4.1
async-lru                 2.0.4
attrs                     24.2.0
babel                     2.16.0
beautifulsoup4            4.12.3
bleach                    6.2.0

[... snip ... snip ... snip ...]

webencodings              0.5.1
websocket-client          1.8.0
wheel                     0.44.0

Packages installés pour l'autre environnement :

❯ /Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/bin/python3 -m pip list
Package           Version
----------------- -------
aiohttp           3.9.1
aiosignal         1.3.1
altgraph          0.17.2
async-timeout     4.0.3
attrs             23.1.0
black             23.12.0

[... snip ... snip ... snip ...]

wheel             0.37.0
yarl              1.9.4

Il y en a d'autres. Comme chaque projet va nécessiter des modules spécifiques il est important d'installer les modules dans le bon environnement.

Usage

Tout projet informatique va utiliser un environnement python via son interpréteur. Il utilisera ses modules, voir en installera de nouveaux qui iront se placer dans le dossier lib/python<version>/ (dans mon environnement courant c'est le dossier lib/python3.13/).

La gestion de ces modules peut s'avérer fastidieuse car :

  1. si vous partagez votre code, il faut une liste des modules dont dépend votre projet pour être utilisé et qu'il faut installer
  2. il faut faire attention aux versions car un changement de version d'un module peut entraîner des changements dans son comportement et casser votre projet

La première solution qui vient à l'esprit est de distribuer les modules en même temps que votre projet, dans un dossier dédié. C'est cependant une très mauvaise idée ! En effet :

Les remarques ci-dessus mènent à une unique conclusion :

Il faut utiliser un outil de gestion des dépendances qui s'occupera d'installer, de maintenir à jour et d'éviter les incompatibilités d'une liste de modules dont dépend le projet.

La solution utilisée par python est de permettre de créer facilement un environnement python dédié pour chaque projet.

Création d'un environnement

Nous utiliserons le module venv, qui doit normalement être disponible.

installation du module venv sous Linux

Le module venv n'est habituellement pas installé sous Linux/Ubuntu. Il faut l'installer en plus avec la commande :

sudo apt install python3-venv

Le but de ce module est de créer un environnement python vierge (sans aucun autre module que les modules essentiels), nommé environnement virtuel, dans un dossier.

Par défaut, ce dossier s'appelle .venv (il est donc caché) et est placé à la racine de votre site.

Avec vscode

Lorsque l'on a changé d'environnement, on a vu que vscode propose de créer un nouvel environnement virtuel.

Dans le projet "virt-python" :

  1. cliquez sur l'environnement python courant :
  2. choisissez "+ Créer un environnement virtuel..." dans le menu déroulant création 1
  3. Choisissez "Venv" si vscode vous propose de choisir création 2
  4. choisissez un interpréteur. C'est puis qui sera utilisé pour créer l'environnement virtuel. Cela va uniquement déterminer la version de python du nouvel environne,ent, aucun module de l'environnement d'origine ne sera dupliqué création 3
  5. L'environnement est crée. Si tout s'est bien passé, ce nouvel environnement est devenu celui de vscode : création 4

En exécutant le programme avec vscode, on obtient bien le nouvel environnement :

création 5

Dans la liste de fichiers, on voit que le nouvel environnement a été créé dans le dossier du projet, dans un dossier nommé .venv/.

Ce dossier n'est pas directement visible du terminal car il commence par un ., il est caché :

ls
main.py 

Pour le voir, il faut ajouter un paramètre :

ls -a
.     ..    .venv     main.py 

Le fait que le dossier soit caché ne change pas grand chose. On peut très bien créer des environnement virtuels dans des dossiers non caché, comme venv/ par exemple. C'est que nous allons faire maintenant.

À la main

On peut créer les environnement directement avec le terminal.

Supprimez l'environnement précédemment crée avec vscode en :

  1. supprimant le dossier .venv
  2. reprenant l'interpréteur par défaut

Vous devez revenir à l'état suivant :

création terminal

Puis dans le terminal, on crée l'environnement en utilisant le module venv :

❯ python -m venv venv/

Ceci a pour conséquence de créer un environnement virtuel dans le dossier venv du dossier du projet. Notez que l'on ne l'a pas appelé .venv : les environnement virtuels peuvent s'appeler .venv (dossier commençant par un . donc caché) ou venv (ne commençant pas par un . donc visible) vscode les reconnait tout de même :

création terminal 2

Modules

Un nouvel environnement vient sans aucun module d'installé :

❯ venv/bin/python -m pip list
Package Version
------- -------
pip     24.2

Utilisation

On peut bien sur utiliser vscode et placer l'environne,ent virtuel sur celui que nous venons de créer, on utiliser l'interpréteur directement depuis le terminal :

L'exécution donne chez moi :

environnement : /Users/fbrucker/Documents/temp/virt-python/.venv

sous Windows

Script execution policy sous windows.

Pour la connaître :

Get-ExecutionPolicy

Pour la modifier :

Set-ExecutionPolicy Unrestricted

Activation

On peut activer l'environnement virtuel à la main grace à une commande qui dépend de votre environnement :

Chez moi cela donne :

❯ python main.py
environnement : /opt/homebrew/opt/python@3.13/Frameworks/Python.framework/Versions/3.13
❯ source venv/bin/activate
❯ python main.py
environnement : /Users/fbrucker/Documents/temp/virt-python/venv

Après activation, en tapant python, c'est bien l'environnement virtuel qui est exécuté.

Cette transformation est liée au terminal. Si vous en changez, il faudra re activer l'environnement.

Activer un environnement, c'est associer le programme python avec l'environnement virtuel pour le terminal dans laquelle la commande est exécutée.

ajout de modules

Peut se faire comme on fait depuis toujours :

[nom de l'interpréteur] -m pip install [nom du module]

Si l'on veut par exemple installer le module numpy pour l'environnement virtuel :

Si l'environnement virtuel est activé on peut tout simplement utiliser :

python -m pip install numpy

Voir utiliser directement pip puisqu'il est directement lié à notre environnement :

pip install numpy

Activer permet de ne pas se soucier du chemin, et permet d'avoir les même commandes sous windows et mac/Linux.

Gestion des environnements virtuels

Partage des modules

Lorsque l'on partage son projet, on ne va pas donner son environnement virtuel en même temps que son code, on ne donne que le code et la liste des modules à installer.

On procède alors comme suit :

  1. on installe un à un tous les modules nécessaires à notre projet avec l'interpréteur de l'environnement virtuel. Comme rien n'est installé initialement, seuls les modules utiles au projet sont installés
  2. on utilise une commande de pip qui sauvegarde tous les modules dans un fichier nommé requirement.txt : venv/bin/python -m pip freeze > requirements.txt

La commande précédente a créée un fichier requirements.txt qui contient tous les modules installés.

Par exemple chez moi, j'ai juste installé le module pytest et mon fichier requirements.txt est :

iniconfig==2.0.0
packaging==24.0
pluggy==1.5.0
pytest==8.2.1

Il contient le module pytest, ses dépendances et les versions installées.

Pour partager votre code, vous n'avez qu'à donner le fichier requirements.txt en plus de celui-ci. La personne recevant votre code :

  1. créera un nouvel environnement virtuel
  2. exécutera la commande venv/bin/python -m pip install -r requirements.txt qui installera tous les modules du fichier requirements.txt.

Le lien ci-dessous explicite le format du fichier requirements.txt :

Poetry

La méthode de partage précédente nécessite plusieurs opérations à effectuer à la main. Il existe des outils plus puissant permettant de gérer plus efficacement le partage et le maintient de projets, nous allons en montrer un :

TBD : faire un exemple. Attention à ce que venv soit bien dans le dossier du projet