Leçon 09-1 — pip et environnements virtuels

1. Objectif

À la fin de cette leçon tu sauras : créer un environnement virtuel (venv) pour un projet, l'activer et le désactiver sous Git Bash et sous PowerShell, installer des bibliothèques dedans avec pip, vérifier QUEL Python et quel pip tournent réellement, générer et utiliser un requirements.txt, et expliquer pourquoi on ne committe jamais un venv.

2. Pourquoi c'est important

Jusqu'ici tu n'as utilisé que la bibliothèque standard : tout était déjà fourni avec Python. Le vrai monde Python, c'est des centaines de milliers de bibliothèques tierces (requests, pytest, pandas…) qu'on installe avec pip. Problème : si tu installes tout dans le Python global de ta machine, tes projets finissent par se marcher dessus (le projet A veut la version 2 d'une bibliothèque, le projet B la version 3), et tu ne sais plus ce dont chaque projet a besoin. L'environnement virtuel règle ça : un dossier par projet, avec son propre Python et ses propres bibliothèques. Toute la suite du niveau 9 (et toute ta vie de développeur Python) repose sur ce mécanisme.

3. Explication simple

Un venv, c'est une boîte à outils privée pour un projet.

Sans venv : une seule caisse à outils pour toute la maison. Tu bricoles la plomberie et l'électricité avec les mêmes outils, ils s'usent, se mélangent, et un jour tu casses la plomberie en changeant un outil pour l'électricité.

Avec venv : une caisse par chantier. Le chantier « météo » a sa caisse avec requests version X ; le chantier « analyse » a la sienne. Tu peux jeter une caisse entière sans toucher aux autres.

Concrètement, trois commandes à connaître :

python -m venv .venv        # 1. créer la caisse (une fois par projet)
source .venv/Scripts/activate   # 2. ouvrir la caisse (à chaque session, Git Bash)
pip install requests        # 3. mettre un outil DANS la caisse

Quand le venv est actif, ton invite de commande affiche (.venv) au début de la ligne. C'est ton témoin visuel : pas de (.venv) = pas de caisse ouverte = pip installe ailleurs.

4. Explication approfondie

a) Ce que python -m venv .venv crée vraiment. Un dossier .venv/ qui contient une copie (légère) de l'interpréteur Python et un dossier Lib/site-packages/ initialement quasi vide. Sous Windows :

.venv/
  Scripts/
    python.exe        ← LE python du projet
    pip.exe           ← LE pip du projet (installe dans ce venv)
    activate          ← script d'activation pour Git Bash
    Activate.ps1      ← script d'activation pour PowerShell
  Lib/
    site-packages/    ← ici atterrissent les bibliothèques installées
  pyvenv.cfg

⚠️ Sous Linux/macOS, Scripts/ s'appelle bin/ — tu verras source .venv/bin/activate dans 90 % des tutos en ligne. Sous Windows, c'est Scripts/. Retiens la traduction, tu la feras toute ta vie.

b) Ce que fait « activer ». Rien de magique : le script d'activation modifie la variable d'environnement PATH de TA session de terminal pour que python et pip pointent d'abord vers .venv/Scripts/. C'est pour ça que :

c) Les deux shells de ta machine. Sous Windows tu croiseras Git Bash et PowerShell ; l'activation diffère :

# Git Bash (syntaxe Unix)
source .venv/Scripts/activate
# PowerShell
.venv\Scripts\Activate.ps1

La première fois, PowerShell peut refuser (« l'exécution de scripts est désactivée ») ; la section 7 montre l'erreur exacte et le remède.

d) LE piège du niveau : le mauvais environnement. pip install installe dans le Python qui exécute pip à cet instant. Si le venv n'est pas activé, tu installes dans le Python global — et ton script lancé avec le python du venv plante avec ModuleNotFoundError alors que « tu viens de l'installer ». Réflexe de survie, à taper au moindre doute :

which python      # Git Bash : quel python répond ?
python -c "import sys; print(sys.executable)"   # marche partout
pip --version     # affiche AUSSI le chemin d'installation de pip

Si le chemin ne contient pas .venv, tu n'es pas dans ton venv. Astuce blindée : python -m pip install requests utilise le pip du python qui exécute la commande — c'est la forme la plus sûre, prends l'habitude.

e) requirements.txt : la liste de courses du projet. Un fichier texte, une bibliothèque par ligne (avec sa version), généré par pip freeze > requirements.txt. N'importe qui (toi dans 6 mois, un collègue, un serveur) recrée l'environnement avec pip install -r requirements.txt. C'est LUI qu'on committe — jamais le venv.

f) Pourquoi on ne committe JAMAIS le venv. Il pèse des dizaines de Mo, contient des .exe propres à TA machine et TON OS (un venv Windows est inutilisable sur Linux), et se régénère en 30 secondes depuis requirements.txt. On ajoute donc .venv/ au .gitignore (⏩ vu au niveau 00). Règle voisine, même logique : on ne committe jamais une clé d'API — quiconque lit ton repo public pourrait l'utiliser à ta place.

Difficulté honnête : cette leçon est la plus « administrative » du niveau et c'est pourtant celle qui fait le plus transpirer sous Windows (activation, shells différents, VS Code qui utilise un autre interpréteur). Prévois une session entière juste pour manipuler : créer, activer, vérifier, casser, recommencer. Tout le reste du niveau en dépend.

5. Exemples commentés

Exemple 1 — cycle de vie complet (Git Bash)

cd ~/Claude/learnpython            # se placer dans le projet
python -m venv .venv               # créer le venv (une seule fois)
source .venv/Scripts/activate      # activer → l'invite affiche (.venv)
python -c "import sys; print(sys.executable)"

Sortie (l'important : le chemin passe par .venv) :

C:\Users\jtron\Claude\learnpython\.venv\Scripts\python.exe

Exemple 2 — le même cycle sous PowerShell

cd C:\Users\jtron\Claude\learnpython
python -m venv .venv               # identique
.venv\Scripts\Activate.ps1         # activation PowerShell
python -c "import sys; print(sys.executable)"
deactivate                         # identique dans les deux shells

Exemple 3 — installer et vérifier

(.venv)$ python -m pip install requests
(.venv)$ pip list

Sortie (versions indicatives) :

Package            Version
------------------ ---------
certifi            2025.10.5
charset_normalizer 3.4.4
idna               3.11
pip                25.3
requests           2.33.0
urllib3            2.5.0

Remarque : tu as demandé requests, tu en reçois cinq. pip a installé aussi les dépendances de requests — les bibliothèques dont il a lui-même besoin. C'est normal et automatique.

Exemple 4 — geler et reproduire l'environnement

(.venv)$ pip freeze > requirements.txt   # photographie les versions exactes
(.venv)$ cat requirements.txt
certifi==2025.10.5
charset_normalizer==3.4.4
idna==3.11
requests==2.33.0
urllib3==2.5.0

Sur une autre machine (ou après avoir supprimé .venv/) :

python -m venv .venv
source .venv/Scripts/activate
pip install -r requirements.txt    # recrée l'environnement à l'identique

Exemple 5 — prouver l'isolation

(.venv)$ deactivate                # sortir du venv
$ python -c "import requests"      # Python GLOBAL

Sortie (si requests n'est pas installé globalement) :

ModuleNotFoundError: No module named 'requests'

C'est exactement ce qu'on veut : la bibliothèque existe DANS le venv, pas ailleurs. L'isolation fonctionne.

6. Erreurs fréquentes

1) pip install sans venv activé

$ pip install requests        # pas de (.venv) dans l'invite !
$ source .venv/Scripts/activate
(.venv)$ python mon_script.py
ModuleNotFoundError: No module named 'requests'

La bibliothèque est partie dans le Python global ; le venv, lui, est vide. Correction : activer D'ABORD, installer ENSUITE. Vérifier avec pip --version (le chemin affiché doit contenir .venv).

2) Copier la commande Linux des tutos

$ source .venv/bin/activate
bash: .venv/bin/activate: No such file or directory

Sous Windows le dossier s'appelle Scripts, pas bin. Correction : source .venv/Scripts/activate.

3) VS Code qui utilise un autre interpréteur

Le terminal dit (.venv), mais le bouton ▶ « Run » de VS Code plante avec ModuleNotFoundError. VS Code choisit son interpréteur indépendamment du terminal : Ctrl+Shift+P → « Python: Select Interpreter » → choisir celui qui contient .venv. En bas à droite de VS Code, l'interpréteur actif est affiché en permanence — prends l'habitude d'y jeter un œil.

4) Committer le venv

git add .
# ... 4 000 fichiers ajoutés, le repo pèse 60 Mo

Aucun message d'erreur — c'est un bug de discipline, pas de syntaxe. Correction : .venv/ dans .gitignore AVANT le premier git add. Si c'est déjà commité : git rm -r --cached .venv puis ajouter la ligne au .gitignore.

5) Créer le venv avec le mauvais Python

Si plusieurs Python cohabitent sur la machine, python -m venv .venv copie celui qui répond à python. Résultat possible : un venv en 3.9 alors que tu codes pour 3.14. Vérifie AVANT de créer : python --version. Le venv héritera de cette version pour toute sa vie.

6) Renommer ou déplacer le dossier du projet

Un venv contient des chemins absolus figés à la création. Après un renommage/déplacement du dossier parent, l'activation semble marcher mais pip plante bizarrement. Correction : supprimer .venv/ et le recréer (30 secondes grâce à requirements.txt — c'est exactement pour ça qu'il existe).

7. Lire les messages d'erreur

L'erreur emblématique : ModuleNotFoundError

Traceback (most recent call last):
  File "C:\Users\jtron\Claude\learnpython\weather.py", line 1, in <module>
    import requests
ModuleNotFoundError: No module named 'requests'

Lecture (de bas en haut, comme toujours) :

  1. Dernière ligne : Python ne trouve pas le module requests — dans l'environnement qui exécute ce script.
  2. Ce message ne dit PAS « requests n'est installé nulle part ». Il dit : « pas ici ». Diagnostic en deux commandes : python -c "import sys; print(sys.executable)" (qui exécute ?) puis pip --version (où pip installe-t-il ?). Si les deux chemins ne pointent pas vers le même environnement, tu as trouvé le bug.
  3. Autre cause fréquente : faute de frappe dans l'import (import request sans s → même erreur, module inexistant).

L'erreur PowerShell à la première activation

.venv\Scripts\Activate.ps1 : Impossible de charger le fichier ... car
l'exécution de scripts est désactivée sur ce système. Pour plus
d'informations, consultez about_Execution_Policies ...

PowerShell bloque par défaut l'exécution de scripts non signés. Remède standard (à faire une fois, dans PowerShell) :

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

RemoteSigned = les scripts locaux (comme Activate.ps1) passent, les scripts téléchargés doivent être signés. C'est le réglage recommandé par la doc Python elle-même.

pip : commande introuvable / 'pip' n'est pas reconnu

Le PATH ne contient pas pip. Contournement universel : passer par Python lui-même — python -m pip install .... Si python non plus n'est pas reconnu, c'est l'installation de Python qui n'est pas dans le PATH (⏩ revu au niveau 00).

8. Exercices — faciles

Règles : travaille dans un dossier bac-à-sable, par exemple lessons/level-09-automatisation-apis-donnees/exercices/mes-reponses/sandbox-venv/. Note tes commandes et observations dans ex-09-1-notes.md au fur et à mesure : les exercices de cette leçon se font au terminal, pas dans un .py.

a) Crée un dossier demo-venv/, crée un venv dedans, active-le (dans ton shell habituel), et prouve avec UNE commande que le python actif est bien celui du venv. Note la commande et sa sortie.

b) Venv activé, exécute pip list. Note ce qu'il contient. Désactive (deactivate), relance pip list. Explique en une phrase la différence observée (ou son absence, selon ta machine).

c) Active le venv des exercices précédents et installe requests avec la forme blindée (python -m pip ...). Vérifie l'installation SANS écrire de script : une seule commande python -c "..." qui importe et affiche la version (requests.__version__).

9. Exercices — moyens

a) Génère le requirements.txt du venv de l'exercice 8-c. Supprime ensuite complètement le dossier .venv/, puis reconstruis un environnement identique en deux commandes à partir du fichier. Vérifie avec pip list que les versions correspondent. C'est la manœuvre « nouveau PC » — chronomètre-la.

b) L'activation croisée : si ton exercice 8-a était en Git Bash, refais-le en PowerShell (et inversement). Note les DEUX commandes d'activation dans ton journal. Si PowerShell refuse d'exécuter le script, lis l'erreur, identifie-la dans la section 7 et applique le remède.

c) Provoque volontairement LE piège du niveau : venv désactivé, crée check.py contenant juste import requests (dans un dossier SANS venv actif, avec un Python global qui n'a pas requests — sinon utilise un nom de module que tu n'as jamais installé). Lance-le, lis le traceback, puis écris dans ton journal la checklist de diagnostic en 3 commandes que tu utiliseras à chaque ModuleNotFoundError.

10. Exercices — difficiles

a) Écris un script env_report.py qui affiche un diagnostic complet de l'environnement qui l'exécute : chemin de l'interpréteur, version de Python, « venv actif : oui/non », et la liste des paquets tiers installés. Le script ne doit utiliser QUE la bibliothèque standard (sys, importlib.metadata) — il doit tourner même dans un venv vide. Lance-le deux fois (venv activé / désactivé) et compare.

11. Mini-projet lié — « kit de démarrage projet »

Prépare le terrain des leçons suivantes (20–30 min) : dans exercices/mes-reponses/, crée le dossier meteo-projet/ avec :

  1. un venv fonctionnel (.venv/) où requests est installé ;
  2. un requirements.txt généré ;
  3. un .gitignore contenant .venv/ ;
  4. un README.md de 5 lignes : comment recréer l'environnement sur une machine neuve (les commandes exactes, pour Git Bash ET PowerShell).

Test final : demande à quelqu'un (ou à toi-même, de mémoire, terminal fermé puis rouvert) de recréer l'environnement en suivant UNIQUEMENT ton README. Ce dossier resservira tel quel dans les leçons 09-2 et 09-3.

12. Correction / méthode de correction

Les solutions détaillées sont dans solutions/serie-09-1-solutions.md.

Méthode : (1) finis TOUS les exercices avant d'ouvrir les solutions ; (2) pour cette leçon, compare surtout les commandes de vérification — le réflexe « quel Python tourne ? » compte plus que la réussite du premier coup ; (3) note dans ton journal chaque erreur d'environnement rencontrée et sa solution : c'est un bêtisier qui vaut de l'or ; (4) refais le cycle créer→activer→installer→geler de mémoire demain.

13. À retenir

14. Questions de révision

  1. Que modifie concrètement le script d'activation d'un venv, et pourquoi l'effet disparaît-il quand on ferme le terminal ?
  2. Quelles sont les deux commandes d'activation sous Windows, selon le shell ?
  3. Ton script plante avec ModuleNotFoundError juste après un pip install réussi : quelles sont les deux commandes de diagnostic, et que compares-tu ?
  4. Pourquoi python -m pip install est-il plus sûr que pip install ?
  5. Que contient un requirements.txt, comment le génère-t-on, comment l'utilise-t-on ?
  6. Donne trois raisons de ne jamais committer un venv.
  7. Pourquoi pip list affiche-t-il cinq paquets alors que tu n'en as installé qu'un ?
  8. Comment vérifier, en Python, qu'on tourne dans un venv ?

15. Checklist de compréhension

Si une case reste vide : refais les exercices de la section correspondante demain, AVANT d'ouvrir la leçon suivante.

16. Commit conseillé

git add lessons/level-09-automatisation-apis-donnees/exercices/mes-reponses/
git commit -m "exercises: complete lesson 09-1 pip and virtual environments"

Vérifie AVANT de committer que git status ne liste aucun fichier de .venv/ — c'est le contrôle qualité de cette leçon. Puis, si c'est ta fin de session : entrée de journal + git push.