Tutoriel Python - Partie 2 : Environnements virtuels

← Partie 1 : Syntaxe Python | Retour aux tutoriels | Partie 3 : Packaging et publication →

Objectif de cette page: partir de zéro sur les environnements virtuels Python, puis aller jusqu'à une utilisation complète en contexte projet et équipe.

Parcours d'apprentissage (novice vers expert)

Fonctionnement: suis les sections dans l'ordre puis valide chaque "Sortie attendue" avant de continuer.

1. Pourquoi utiliser un environnement virtuel ?

Un environnement virtuel isole les dépendances Python d'un projet. Chaque projet a ses propres versions de bibliothèques, sans casser les autres projets.

Problème sans isolation

Objectif: comprendre ce qui se passe quand on installe des bibliothèques globalement sur la machine.

Fonctionnement: le deuxième projet force une autre version de la même bibliothèque et peut casser le premier projet.

# Projet A veut requests 2.31
pip install requests==2.31.0

# Projet B veut requests 2.26
pip install requests==2.26.0

# La seconde installation écrase la première si tout est global.

Bénéfices concrets

Exemple concret: deux projets incompatibles

Objectif: montrer comment deux projets avec besoins différents peuvent coexister sans conflit.

Fonctionnement: chaque dossier possède son propre .venv; les paquets installés dans un projet ne sont pas visibles dans l'autre.

# Projet web legacy
mkdir api-legacy
cd api-legacy
py -m venv .venv
.\.venv\Scripts\Activate.ps1
py -m pip install "Django==3.2.25"
py -m pip freeze > requirements.txt

# Projet data plus récent (autre dossier)
cd ..
mkdir data-modern
cd data-modern
py -m venv .venv
.\.venv\Scripts\Activate.ps1
py -m pip install "pandas==2.2.3"
py -m pip freeze > requirements.txt

Chaque dossier garde son propre environnement. Les versions de Django et pandas n'entrent jamais en conflit.

2. Palier A: initiation guidée (débutant)

2.1 Vérifier Python et pip

Objectif: confirmer que Python et pip sont bien installés avant de continuer.

Fonctionnement: les commandes affichent les versions; si une commande échoue, il faut corriger l'installation Python avant tout.

# Windows
py --version
py -m pip --version

# Linux / macOS
python3 --version
python3 -m pip --version

Sortie attendue: un numéro de version Python (ex: 3.12.x) et une version pip.

Erreur fréquente: "py n'est pas reconnu". Solution: utiliser python ou python3 selon ta machine, puis vérifier l'installation Python.

2.2 Créer un environnement virtuel

Objectif: créer un espace isolé de dépendances pour ce projet uniquement.

Fonctionnement: venv génère un dossier .venv contenant un interpréteur Python et un pip propres au projet.

# Windows (PowerShell ou CMD)
py -m venv .venv

# Linux / macOS
python3 -m venv .venv

Sortie attendue: la commande se termine sans message d'erreur et le dossier .venv apparaît dans le projet.

Erreur fréquente: permission refusée dans le dossier courant. Solution: créer le projet dans un dossier utilisateur (ex: Documents).

2.2 bis Arborescence recommandée du projet

Objectif: adopter une structure de dossier claire et maintenable dès le début.

Fonctionnement: le code est rangé dans src/, les tests dans tests/, et les dépendances sont décrites dans requirements.txt.

mon-projet/
├── .venv/                 # environnement virtuel local
├── src/                   # code Python
├── tests/                 # tests
├── requirements.txt       # dépendances figées
├── README.md              # mode d'emploi
└── .gitignore

2.3 Activer l'environnement

Objectif: faire en sorte que les commandes python/pip du terminal ciblent le .venv du projet.

Fonctionnement: l'activation modifie temporairement PATH dans le shell; le prompt affiche généralement (.venv).

# Windows PowerShell
.\.venv\Scripts\Activate.ps1

# Windows CMD
.\.venv\Scripts\activate.bat

# Linux / macOS
source .venv/bin/activate

Quand l'environnement est actif, le prompt affiche en général (.venv).

Sortie attendue: le prompt commence par (.venv), par exemple (.venv) PS C:\projet>.

Erreur fréquente: script bloqué sous PowerShell. Solution: utiliser la section dépannage "Exécution de script bloquée" plus bas.

2.4 Installer des dépendances

Objectif: ajouter les bibliothèques nécessaires au projet dans l'environnement actif.

Fonctionnement: pip télécharge les paquets et leurs dépendances dans .venv, puis pip list permet de vérifier le résultat.

# Exemple simple
pip install requests flask

# Vérifier les paquets installés
pip list

Sortie attendue: pip affiche "Successfully installed ..." puis pip list montre requests et flask.

Erreur fréquente: timeout réseau ou SSL. Solution: relancer la commande, vérifier proxy/connexion, puis tester avec py -m pip install requests.

2.4 bis Exemple concret avec mini script

Objectif: valider immédiatement qu'une bibliothèque installée fonctionne dans le projet.

Fonctionnement: on installe requests, on écrit un script qui appelle une API publique, puis on exécute le script dans le même .venv.

# 1) Installer une dépendance
py -m pip install requests==2.32.3

# 2) Créer src/app.py
import requests

res = requests.get("https://api.github.com")
print(res.status_code)

# 3) Lancer le script
py src/app.py

Sortie attendue: le script affiche 200 (ou parfois 301/403 selon le réseau), ce qui prouve que requests fonctionne.

Erreur fréquente: "No such file src/app.py". Solution: créer le dossier src puis le fichier app.py avant exécution.

2.5 Sauvegarder les dépendances

Objectif: figer l'état exact de l'environnement pour le partager et le reconstruire plus tard.

Fonctionnement: pip freeze exporte les versions installées dans requirements.txt, qui devient la référence du projet.

# Export des versions installées
pip freeze > requirements.txt

Lecture de l'exemple: chaque ligne de requirements.txt correspond à un package avec sa version précise.

# Exemple de requirements.txt généré
certifi==2025.8.3
charset-normalizer==3.4.1
idna==3.10
requests==2.32.3
urllib3==2.5.0

Sortie attendue: le fichier requirements.txt est créé dans le dossier courant.

Erreur fréquente: requirements vide. Cause probable: environnement non activé. Solution: activer .venv puis relancer pip freeze.

2.6 Reproduire l'environnement ailleurs

Objectif: reconstruire rapidement le même contexte sur une autre machine.

Fonctionnement: on recrée .venv puis pip lit requirements.txt pour installer exactement les versions attendues.

# Créer et activer un venv
py -m venv .venv
.\.venv\Scripts\Activate.ps1

# Réinstaller exactement les dépendances
pip install -r requirements.txt

Sortie attendue: pip installe les mêmes versions que dans requirements.txt sans conflit.

Erreur fréquente: "Could not find a version" pour un package. Solution: vérifier la version Python du projet et adapter les contraintes.

2.6 bis Cas réel: nouveau PC ou CI

Objectif: simuler un vrai scénario d'intégration dans une équipe ou dans un pipeline CI.

Fonctionnement: après clone, on reconstruit tout depuis zéro puis pip check confirme la cohérence des dépendances.

# Git clone du projet
git clone https://example.com/mon-projet.git
cd mon-projet

# Reconstruction complète
py -m venv .venv
.\.venv\Scripts\Activate.ps1
py -m pip install --upgrade pip
py -m pip install -r requirements.txt

# Vérification
py -m pip check

Sortie attendue: pip check renvoie "No broken requirements found".

Erreur fréquente: conflits de dépendances détectés. Solution: ajuster requirements/constraints puis reconstruire le .venv.

2.7 Désactiver proprement

Objectif: sortir de l'environnement projet quand le travail est terminé.

Fonctionnement: deactivate restaure le terminal vers l'interpréteur Python global.

deactivate

Sortie attendue: le préfixe (.venv) disparaît du terminal.

3. Erreurs fréquentes et dépannage rapide

"pip n'est pas reconnu"

Objectif: contourner les problèmes de PATH sur certaines machines.

Fonctionnement: en passant par py -m pip ou python3 -m pip, on appelle pip via l'interpréteur cible.

# Utiliser toujours pip via Python
py -m pip install -r requirements.txt
# ou
python3 -m pip install -r requirements.txt

Sortie attendue: les paquets s'installent même si la commande pip seule n'est pas accessible.

Exécution de script bloquée sous PowerShell

Objectif: autoriser l'activation du .venv quand PowerShell bloque les scripts.

Fonctionnement: RemoteSigned autorise les scripts locaux; ensuite l'activation du .venv fonctionne normalement.

# Autoriser les scripts pour l'utilisateur courant
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned

# Puis réessayer l'activation
.\.venv\Scripts\Activate.ps1

Sortie attendue: après confirmation, l'activation fonctionne et le prompt affiche (.venv).

Mauvais interprète dans VS Code

Conflit de versions

Objectif: identifier une dépendance source de conflit puis imposer une plage de versions compatible.

Fonctionnement: pip show donne les détails du package et l'installation avec bornes évite les mises à jour risquant de casser le projet.

# Voir qui depend de quoi
pip show requests

# Mettre à jour de manière contrôlée
pip install "requests>=2.31,<3.0"

Sortie attendue: pip installe une version conforme a la plage demandee, sans passer en 3.x.

Erreur ModuleNotFoundError malgré installation

Objectif: vérifier que le code et pip utilisent bien le même interpréteur Python.

Fonctionnement: on compare le chemin de l'exécutable Python et les infos du package installé pour détecter un décalage d'environnement.

# Vérifier l'interpréteur en cours
py -c "import sys; print(sys.executable)"

# Vérifier l'installation dans le même interpréteur
py -m pip show requests

Sortie attendue: le chemin de sys.executable contient .venv et pip show retourne les infos du package.

Si les chemins ne pointent pas vers .venv, active d'abord l'environnement puis relance la commande.

4. Palier B: exploitation complète (autonomie avancée)

4.1 Stratégie dev/test/prod

Conserver l'isolation par projet et séparer les dépendances par usage.

Objectif: éviter d'embarquer les outils de développement en production.

Fonctionnement: un fichier base est partagé, puis dev.txt et prod.txt ajoutent uniquement les paquets nécessaires à leur contexte.

# requirements/base.txt
fastapi==0.116.0
uvicorn==0.35.0

# requirements/dev.txt
-r base.txt
pytest==8.4.1
ruff==0.8.4

# requirements/prod.txt
-r base.txt
gunicorn==23.0.0

Sortie attendue: 3 fichiers de dépendances avec un socle commun et des couches spécifiques par contexte.

Exploitation complète: un membre de l'équipe installe uniquement dev.txt en local, tandis que la production utilise prod.txt.

4.2 Contraintes et verrouillage des versions

Pour stabiliser les builds d'equipe, on peut imposer des bornes de versions avec un fichier de contraintes.

Objectif: garder des dépendances transverses sous contrôle quand plusieurs libs tirent des versions différentes.

Fonctionnement: le fichier constraints.txt fixe des limites globales appliquees au moment de l'installation.

# constraints.txt
urllib3<3.0
idna>=3.7,<4.0

# Installation avec contraintes
pip install -r requirements/dev.txt -c constraints.txt

Sortie attendue: l'installation respecte les limites de constraints.txt même pour les dépendances indirectes.

4.2 bis Verrouillage reproductible avec pip-tools (option pro)

Objectif: obtenir un lock file déterministe à partir d'une liste courte de dépendances directes.

Fonctionnement: requirements.in contient l'intention; pip-tools calcule et écrit toutes les versions résolues dans requirements.txt.

# Installation de l'outil
py -m pip install pip-tools

# requirements.in contient les dépendances directes
echo fastapi> requirements.in
echo uvicorn>> requirements.in

# Génération d'un lock file déterministe
py -m piptools compile requirements.in -o requirements.txt

# Installation strictement conforme
py -m pip install -r requirements.txt

Sortie attendue: requirements.txt contient toutes les dépendances résolues et peut être réutilisé en CI.

4.3 Workflow equipe reproductible

Objectif: standardiser les étapes d'arrivée d'un nouveau développeur sur le projet.

Fonctionnement: clone, création du .venv, installation, vérification; tout le monde suit la même séquence.

# 1) Nouveau clone
py -m venv .venv
.\.venv\Scripts\Activate.ps1

# 2) Installer les dépendances dev
py -m pip install -r requirements/dev.txt

# 3) Vérifier l'état
py -m pip check
py -m pip list

Sortie attendue: tout membre de l'équipe obtient le même inventaire de packages.

4.3 bis Convention d'équipe recommandée

4.4 Automatisation minimale (scripts)

Objectif: supprimer les erreurs humaines dues aux commandes tapées à la main.

Fonctionnement: le script setup-dev.ps1 encapsule création, activation, installation et vérification dans un flux unique.

# scripts/setup-dev.ps1
py -m venv .venv
.\.venv\Scripts\Activate.ps1
py -m pip install --upgrade pip
py -m pip install -r requirements/dev.txt
py -m pip check

Sortie attendue: un seul script prépare un environnement dev fonctionnel de bout en bout.

Ce script permet à un nouveau membre de l'équipe d'être opérationnel en quelques minutes.

4.5 Hygiène des dépendances

Objectif: détecter rapidement les incompatibilités et garder une vision claire des packages installés.

Fonctionnement: pip check détecte les incohérences de dépendances, pip list donne l'inventaire courant.

# Vérifier les conflits cassés
py -m pip check

# Lister de manière concise
py -m pip list --format=columns

Sortie attendue: aucune rupture dans les requirements et une liste lisible des versions installées.

Objectif: identifier les mises à jour possibles avant un sprint de maintenance.

Fonctionnement: pip list --outdated affiche les paquets pour lesquels une version plus récente existe.

# Identifier les dépendances obsolètes
py -m pip list --outdated

Sortie attendue: tableau des paquets ayant une version plus récente disponible.

4.6 Checklist pré-production

4.7 Exemple CI (GitHub Actions)

Objectif: exécuter automatiquement l'installation et les tests à chaque push.

Fonctionnement: la CI recrée un environnement propre, installe requirements/dev.txt, puis lance pytest pour valider le code.

name: tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - name: Install deps
        run: |
          python -m pip install --upgrade pip
          python -m pip install -r requirements/dev.txt
      - name: Run tests
        run: pytest

Sortie attendue: à chaque push, la CI reconstruit l'environnement et exécute les tests automatiquement.

5. Astuces pro rapides

Lecture de l'exemple: ajouter .venv dans .gitignore évite d'envoyer des centaines de fichiers inutiles dans le dépôt Git.

# .gitignore (extrait)
.venv/
__pycache__/
*.pyc

6. Mini labo pratique: de zéro à projet exécutable

But: construire un mini outil CLI Python dans un environnement virtuel reproductible.

6.1 Initialisation

Objectif: préparer un projet neuf avec un environnement propre et une dépendance externe.

Fonctionnement: on crée le dossier, le .venv, puis on installe rich qui servira pour l'affichage console.

mkdir labo-venv
cd labo-venv
py -m venv .venv
.\.venv\Scripts\Activate.ps1
py -m pip install --upgrade pip
py -m pip install rich==13.9.4

Sortie attendue: le projet est initialisé et rich apparaît dans pip list.

6.2 Code de l'application

Objectif: écrire un script minimal qui prouve que la dépendance installée est bien utilisable.

Fonctionnement: rich est importé, puis un message coloré avec horodatage est affiché dans le terminal.

# fichier: src/main.py
from datetime import datetime
from rich.console import Console

console = Console()
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
console.print(f"[bold green]Application OK[/] - {now}")

Sortie attendue: un message vert avec date/heure s'affiche lorsque le script est exécuté.

6.3 Exécution et vérification

Objectif: valider l'exécution du programme et capturer l'état exact des dépendances.

Fonctionnement: on lance le script, puis pip freeze génère requirements.txt pour rendre le labo reproductible.

mkdir src
py src/main.py
py -m pip freeze > requirements.txt
type requirements.txt

Sortie attendue: exécution OK puis contenu de requirements.txt visible dans le terminal.

6.4 Rebuild complet (simulation nouvelle machine)

Objectif: prouver que le projet peut être reconstruit sans dépendre de l'état précédent de la machine.

Fonctionnement: on supprime le .venv, on le recrée, on réinstalle via requirements.txt et on relance le script.

deactivate
Remove-Item -Recurse -Force .venv

py -m venv .venv
.\.venv\Scripts\Activate.ps1
py -m pip install -r requirements.txt
py src/main.py

Sortie attendue: l'application refonctionne après reconstruction complète, preuve que le projet est reproductible.

6.5 Critère de réussite

7. Résumé

Tu sais maintenant: créer, activer, maintenir et reproduire des environnements virtuels Python.

Tu peux aussi aller plus loin avec un workflow équipe fiable (dev/test/prod, contraintes, scripts, checklist).

Défi progression (vers expert)

Mission: prends un petit projet Python, supprime son environnement actuel, puis reconstruis-le uniquement à partir de README + requirements.

Revenir à la Partie 1 | Continuer vers la Partie 3 → | Retour aux tutoriels