Installez deux projets Python sur la même machine et le second peut casser le premier. L’un a besoin de requests==2.28, l’autre de requests==2.32, et pip n’a qu’un seul répertoire site-packages global dans lequel écrire. La dernière installation gagne, silencieusement. Vous le découvrez quand l’autre projet commence à lever des erreurs qui n’ont rien à voir avec le code que vous venez de modifier.
Un environnement virtuel donne à chaque projet son propre site-packages. Rien de global n’est touché, et deux projets peuvent dépendre de versions incompatibles de la même bibliothèque sans que l’un remarque l’autre.
Qu’est-ce qu’un environnement virtuel Python ?
Un venv est un répertoire avec trois éléments : un interpréteur Python (un lien symbolique vers celui du système sur Linux et macOS), un fichier pyvenv.cfg qui pointe vers cette installation de base, et un dossier site-packages où pip install écrit les paquets. L’activer place le répertoire bin du venv (Scripts sous Windows) en tête du PATH de votre shell, si bien que python et pip résolvent vers les copies du venv plutôt que celles du système.
C’est tout le mécanisme. Il n’y a ni isolation du système de fichiers ni seconde copie de Python. Un venv change seulement où le shell trouve deux binaires et d’où les imports sont résolus, c’est pourquoi en créer un prend une seconde et en supprimer un se fait avec rm -rf .venv. Si vous devez aussi isoler le système d’exploitation et le système de fichiers, c’est le travail d’un conteneur, pas d’un venv.
Comment créer et activer un venv ?
La bibliothèque standard fournit le module venv, il n’y a donc rien à installer :
| |
.venv est le nom conventionnel, et uv ainsi que la plupart des éditeurs le recherchent par défaut. L’activation dépend de votre shell :
| OS / shell | Commande |
|---|---|
| Linux / macOS (bash, zsh) | source .venv/bin/activate |
| Windows (cmd.exe) | .venv\Scripts\activate.bat |
| Windows (PowerShell) | .venv\Scripts\Activate.ps1 |
Une installation Windows récente bloque les scripts PowerShell, y compris celui d’activation. Autorisez les scripts créés localement, une fois par utilisateur :
| |
Une fois le venv activé, votre invite affiche le préfixe (.venv) et which python (where python sous Windows) pointe dans .venv. Lancez deactivate pour revenir en arrière. C’est une fonction shell définie par le script d’activation, pas un programme à part.
L’activation est optionnelle. .venv/bin/python script.py et .venv/bin/pip install requests fonctionnent sans elle, et c’est ainsi que les pipelines CI et les éditeurs appellent le venv en coulisses.
Avec plusieurs versions de Python installées, python -m venv utilise le premier python que le shell trouve, qui n’est souvent pas celui que vous visiez. Précisez la version : python3.12 -m venv .venv sur Linux et macOS. Sous Windows, utilisez le lanceur py fourni avec Python, qui choisit une version par numéro indépendamment du PATH : py -3.12 -m venv .venv.
Comment installer des paquets avec pip et requirements.txt ?
Dans un venv actif, pip install <package> fait ce que vous attendez. Pour la reproductibilité, ce qui compte, c’est d’enregistrer ce qui a été installé :
| |
pip freeze écrit chaque paquet installé avec sa version exacte, y compris les dépendances de vos dépendances. Commitez requirements.txt, et toute personne qui clone le projet exécute :
| |
et obtient les versions que vous aviez. Le point faible : le fichier mélange ce que vous avez demandé avec tout ce que pip a ramené au passage. Six mois plus tard, distinguer « j’ai besoin de Flask » de « Flask avait besoin de Werkzeug 3.1.3 » demande de lire toute la liste et de deviner.
pyproject.toml ou requirements.txt : quelle est la différence ?
pyproject.toml n’enregistre que vos dépendances directes, avec des plages de versions :
| |
pip install . lit ce fichier et résout tout l’arbre de dépendances au moment de l’installation. pip install ".[dev]" ajoute le groupe dev par-dessus. Le même fichier contient les métadonnées de packaging si vous publiez un jour le projet, ce pour quoi requirements.txt n’a jamais été conçu.
Ce qu’il ne fait pas, c’est fixer des versions exactes. flask>=3.0 se résout à la version la plus récente disponible le jour de l’installation. Le pinning est le travail d’un lock file, et venv + pip n’en fournissent pas.
Dans une build de conteneur, c’est le fichier que vous copiez avant le reste du code source, afin que la couche des dépendances ne se reconstruise que lorsque pyproject.toml change. Le guide des bonnes pratiques Dockerfile explique pourquoi cet ordre compte pour le cache de build.
Comment utiliser uv à la place de venv et pip ?
uv est un seul binaire Rust qui couvre le travail de venv, pip, pip-tools et pyenv : uv python install 3.12 télécharge et gère les versions de Python comme le fait pyenv, donc uv venv --python 3.12 fonctionne même si cette version n’est pas encore présente sur la machine. Il est aussi assez rapide pour qu’on le remarque : une résolution qui prend plusieurs secondes à pip se termine en une fraction de ce temps.
Installez-le une fois (la documentation astral.sh liste la commande pour chaque plateforme). Vous pouvez ensuite l’utiliser de deux façons.
Comme remplacement direct de venv et pip, si seule la vitesse vous intéresse :
| |
uv venv crée .venv de la même façon que python -m venv .venv, et uv pip install accepte les mêmes arguments que pip. Vous activez le résultat comme n’importe quel autre venv.
En mode projet, qui ajoute le locking :
| |
uv init génère la structure d’un pyproject.toml. uv add y écrit la dépendance, résout tout l’arbre et écrit un fichier uv.lock qui fixe chaque version résolue, transitives incluses, avec des hashes. Ce lock file est la pièce que pip ne produit pas. Commitez à la fois pyproject.toml et uv.lock, et un collègue exécute :
| |
Cela crée .venv s’il manque et installe exactement ce que dit le lock file, pas ce que les plages de versions de pyproject.toml résolvent ce jour-là. uv run script.py effectue la même vérification de synchronisation avant de s’exécuter, si bien que votre environnement ne peut pas dériver du lock file sans que vous le remarquiez.
Comment corriger les erreurs courantes d’environnement virtuel ?
error: externally-managed-environment. Vous avez exécuté pip install hors d’un venv sur Debian 12+, Ubuntu 23.04+, Fedora 38+ ou une distribution similaire, et le Python système a refusé. PEP 668 a introduit un fichier marqueur que le gestionnaire de paquets du système place dans son installation Python pour empêcher pip d’écraser des paquets également gérés par apt ou dnf. Avant cela, un sudo pip install malvenu pouvait casser les outils du système lui-même, de façon pénible à déboguer. Certains guides plus anciens vous disent d’ajouter --break-system-packages. Ne le faites pas : cela ramène exactement la casse que le marqueur empêche. Créez un venv et installez-y.
L’éditeur exécute le mauvais interpréteur. VS Code, PyCharm et les outils similaires reprennent ce que python a résolu à l’ouverture du projet, qui n’est pas forcément celui de votre venv. Les symptômes : des imports qui fonctionnent dans le terminal apparaissent comme non résolus dans l’éditeur, ou un paquet installé cinq minutes plus tôt n’est pas trouvé. Réglez explicitement l’interpréteur de l’éditeur sur .venv/bin/python (.venv\Scripts\python.exe sous Windows).
Le venv a été commité sur git. Ce sont quelques centaines de mégaoctets de binaires plus des chemins absolus dans pyvenv.cfg et les scripts d’activation, donc ça casse dès que quelqu’un clone le dépôt vers un chemin ou un OS différent. Ajoutez .venv/ au .gitignore. Depuis Python 3.13, venv écrit aussi un .gitignore dans le nouvel environnement qui ignore son contenu, mais sur les versions plus anciennes, vous devez le faire vous-même. Commitez requirements.txt, ou pyproject.toml avec uv.lock. Ces fichiers reconstruisent l’environnement n’importe où. Le répertoire lui-même n’a jamais sa place dans le dépôt.
venv, pyproject.toml ou uv : lequel choisir ?
Restez sur venv + pip + requirements.txt pour un petit projet avec peu de dépendances, où vous ne voulez pas d’outillage supplémentaire. Passez à pyproject.toml dès que vous avez des dépendances réservées au développement, comme des test runners et des linters qui ne doivent pas partir en production, ou dès que vous prévoyez de packager le projet.
Ajoutez uv quand la vitesse de résolution commence à peser, ou que vous voulez un lock file commité sans en maintenir un à la main avec pip-tools. Il ne force aucune réécriture : lancez uv init sur un nouveau projet, ou uv venv et uv pip install -r requirements.txt sur un projet existant, et passez à uv add quand vous êtes prêt pour le lock file.