Chapitre 12 — Les outils du développeur : venv, pip et Git¶
⏱️ Durée estimée : 5 à 7 heures (cours + exercices + mini-projet)
📋 Prérequis : avoir terminé le Chapitre 11 — POO avancée, héritage et typage et savoir utiliser un terminal (Chapitre 00).
🎯 Objectifs — À la fin de ce chapitre, tu sauras…
- créer, activer et désactiver un environnement virtuel (venv) sous Windows, macOS et Linux ;
- installer, lister, désinstaller des paquets avec pip et partager tes dépendances avec un fichier requirements.txt ;
- situer les outils modernes uv et pyproject.toml ;
- suivre l'historique de ton code avec Git :
init,status,add,commit,log,diff;- travailler avec des branches, les fusionner et résoudre un conflit simple ;
- publier ton projet sur GitHub et le récupérer ailleurs avec
clone,pushetpull.
Cours¶
Jusqu'ici, tu as écrit du code Python « tout seul dans ton coin » : un fichier, tu l'exécutes, c'est tout. Les vrais projets ont deux besoins supplémentaires :
- Utiliser du code écrit par d'autres (des bibliothèques comme
requests,pandas,flask…) sans casser ton ordinateur ni tes autres projets. → C'est le rôle de venv et pip. - Garder l'historique de ton travail, pouvoir revenir en arrière, essayer des idées sans risque et collaborer. → C'est le rôle de Git et GitHub.
Ces outils ne sont pas du Python à proprement parler, mais aucun développeur ne travaille sans eux. Prends le temps de bien les comprendre : tu t'en serviras dans tous tes projets à venir.
1. Pourquoi des environnements virtuels ?¶
Imagine une cuisine partagée par toute une colocation. Chacun range ses ingrédients dans le même placard. Un jour, Léa remplace le sel par du sel au céleri pour sa recette… et le gâteau de Tom a un goût étrange. 🤢
C'est exactement ce qui arrive quand tu installes toutes tes bibliothèques dans le Python « global » de ton ordinateur :
- le projet A a besoin de
pandasversion 1.x ; - le projet B a besoin de
pandasversion 2.x ; - impossible d'avoir les deux en même temps dans le même placard !
Un environnement virtuel (virtual environment, abrégé venv) est un placard privé par projet : un dossier qui contient sa propre copie de l'interpréteur Python et ses propres bibliothèques. Ce que tu installes dedans ne touche ni les autres projets, ni le Python du système.
mon_projet/
├── .venv/ ← le placard privé (ne se partage pas, ne se commit pas)
│ ├── bin/ ou Scripts/ ← python, pip… de ce projet
│ └── lib/ ← les bibliothèques installées pour ce projet
├── main.py
└── requirements.txt ← la liste de courses (elle, on la partage)
💡 Règle d'or : un projet = un venv. On crée le venv dans le dossier du projet, et on l'appelle par convention
.venv(avec un point, ce qui le cache sur macOS/Linux et le rend facile à reconnaître).
2. Créer, activer et désactiver un venv¶
2.1 Créer le venv¶
Ouvre un terminal dans le dossier de ton projet (dans VS Code : Terminal → Nouveau terminal), puis :
Décortiquons : python3 -m venv signifie « exécute le module venv de Python », et .venv est le nom du dossier à créer. L'opération prend quelques secondes ; un dossier .venv apparaît.
2.2 Activer le venv¶
Créer le venv ne suffit pas : il faut l'activer pour que les commandes python et pip du terminal pointent vers le placard privé.
Une fois activé, le nom du venv s'affiche au début de l'invite du terminal :
C'est ton signal visuel : « je suis dans le placard privé ». À partir de là, sur tous les systèmes, tu peux simplement taper python et pip (plus besoin de python3 ou py).
⚠️ Windows : « l'exécution de scripts est désactivée sur ce système » La première fois, PowerShell peut refuser d'exécuter
Activate.ps1. Lance une seule fois cette commande, puis réessaie :Elle autorise les scripts locaux pour ton utilisateur uniquement.
2.3 Vérifier qu'on est bien dans le venv¶
Si le chemin affiché se termine par .venv, c'est gagné. Autre méthode :
2.4 Désactiver le venv¶
Cette commande est la même partout. Le (.venv) disparaît de l'invite. Fermer le terminal désactive aussi le venv.
2.5 VS Code et le venv¶
VS Code détecte généralement le dossier .venv tout seul et te propose de l'utiliser. Sinon : Ctrl+Maj+P (ou Cmd+Maj+P sur Mac) → Python: Select Interpreter → choisis celui qui contient .venv. Ensuite, chaque nouveau terminal ouvert dans VS Code active automatiquement le venv.
2.6 Supprimer un venv¶
Un venv est jetable : si tu as un doute, supprime le dossier .venv et recrée-le. Comme tes dépendances sont listées dans requirements.txt (voir plus bas), tu ne perds rien.
3. pip : le gestionnaire de paquets¶
pip (Package Installer for Python) télécharge des bibliothèques depuis PyPI (Python Package Index, pypi.org), l'immense catalogue public de paquets Python : plus de 500 000 projets !
💡 Analogie : PyPI est le supermarché, pip est ton chariot, le venv est ton placard.
Toutes les commandes ci-dessous s'exécutent venv activé.
3.1 Installer un paquet¶
pip télécharge requests et ses dépendances (les bibliothèques dont requests a lui-même besoin). Tu peux ensuite l'utiliser :
import requests
reponse = requests.get("https://api.github.com")
print(reponse.status_code) # 200 si tout va bien
Variantes utiles :
pip install requests==2.32.3 # une version précise
pip install "requests>=2.30" # au moins cette version (guillemets : à cause du >)
pip install --upgrade requests # mettre à jour vers la dernière version
pip install rich pandas # plusieurs paquets d'un coup
💡 Astuce robuste :
python -m pip install requestsest équivalent àpip install requests, mais garantit que tu utilises le pip du Python actuel. En cas de doute (surtout sous Windows), préfère cette forme.
3.2 Lister et inspecter¶
pip list # tous les paquets installés, présentation lisible
pip show requests # détails : version, auteur, dépendances, emplacement…
Exemple de sortie de pip list dans un venv tout neuf où l'on a installé requests :
Package Version
------------------ ---------
certifi ...
charset-normalizer ...
idna ...
pip ...
requests ...
urllib3 ...
Tu remarques que certifi, idna, urllib3… ont été installés automatiquement : ce sont les dépendances de requests.
3.3 Désinstaller¶
⚠️ pip uninstall ne retire pas les dépendances qui avaient été installées avec le paquet. Si tu veux repartir de zéro, le plus simple reste de supprimer et recréer le venv.
3.4 pip freeze et le fichier requirements.txt¶
Comment dire à un ami (ou à ton « toi » du futur) quelles bibliothèques installer pour faire tourner ton projet ? On écrit une liste de courses : le fichier requirements.txt.
affiche tous les paquets installés au format nom==version :
On redirige cette sortie dans un fichier avec > :
Et de l'autre côté, sur un autre ordinateur, après avoir créé et activé un venv :
-r signifie « lis la liste dans ce fichier ». En une commande, on retrouve exactement les mêmes versions. 🎉
Tu peux aussi écrire requirements.txt à la main, avec seulement les paquets que tu utilises directement :
| Notation | Signification |
|---|---|
rich |
n'importe quelle version (la plus récente) |
pandas==2.2.2 |
exactement cette version (épinglée) |
requests>=2.30 |
au moins 2.30 |
flask~=3.0 |
compatible avec 3.0 (donc 3.x, mais pas 4.0) |
💡 freeze ou à la main ?
pip freezedonne une reproduction exacte (idéal pour déployer une application). Une liste écrite à la main est plus lisible. Pour débuter,pip freeze > requirements.txtest parfaitement acceptable.
3.5 Le cycle de vie complet¶
# 1. Je crée mon projet et son venv
mkdir meteo && cd meteo
python3 -m venv .venv # Windows : py -m venv .venv
source .venv/bin/activate # Windows : .venv\Scripts\Activate.ps1
# 2. J'installe ce dont j'ai besoin
pip install requests rich
# 3. Je code… puis je sauvegarde la liste
pip freeze > requirements.txt
# 4. Je termine ma session
deactivate
Et pour quelqu'un qui récupère le projet :
cd meteo
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python main.py
4. L'alternative moderne : pyproject.toml et uv¶
Tu croiseras ces deux noms partout ; voici l'essentiel pour ne pas être perdu.
4.1 pyproject.toml¶
pyproject.toml est le fichier de configuration standard d'un projet Python moderne. Il remplace (et dépasse) requirements.txt : il décrit le nom du projet, sa version, la version de Python requise, ses dépendances, et la configuration des outils (pytest, ruff… que tu verras au chapitre 13).
[project]
name = "meteo"
version = "0.1.0"
description = "Affiche la météo dans le terminal"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"requests>=2.30",
"rich",
]
[project.optional-dependencies]
dev = ["pytest", "ruff"]
Le format TOML se lit facilement : des sections entre crochets [...] et des paires clé = valeur.
4.2 uv¶
uv est un outil récent, extrêmement rapide, qui remplace en une seule commande venv + pip (et bien plus : il peut même installer Python pour toi). Il s'installe à part (voir docs.astral.sh/uv). Un aperçu :
uv init meteo # crée le projet avec un pyproject.toml
cd meteo
uv add requests rich # ajoute les dépendances (et crée le .venv tout seul)
uv run main.py # exécute le script dans le venv, sans l'activer
Il sait aussi imiter les commandes classiques :
🧭 Que choisir ? Apprends d'abord
venv+pip+requirements.txt: ils sont livrés avec Python, fonctionnent partout et t'aident à comprendre ce qui se passe. Quand tu seras à l'aise, essaieuv: tu retrouveras les mêmes concepts, en plus confortable.
5. Git : la machine à remonter le temps¶
Tu as sûrement déjà vu des dossiers comme ça :
Git résout ce problème proprement. C'est un logiciel de gestion de versions : il enregistre des photos successives de ton projet (appelées commits), avec un message expliquant ce qui a changé. Tu peux à tout moment :
- voir l'historique complet ;
- comparer deux versions ;
- revenir en arrière ;
- essayer une idée dans une « réalité parallèle » (une branche) sans risque ;
- collaborer à plusieurs sur le même code.
💡 Git ≠ GitHub. Git est le logiciel qui tourne sur ton ordinateur. GitHub est un site web qui héberge des dépôts Git en ligne (comme GitLab, Codeberg ou Bitbucket). Tu peux utiliser Git sans GitHub, mais pas l'inverse.
5.1 Installer et configurer Git¶
- Windows : télécharge « Git for Windows » sur git-scm.com et garde les options par défaut (il installe aussi Git Bash).
- macOS : tape
git --versiondans le terminal ; macOS propose d'installer les outils nécessaires. Oubrew install git. - Linux :
sudo apt install git(Debian/Ubuntu) ousudo dnf install git(Fedora).
Vérifie : git --version.
Ensuite, présente-toi à Git une seule fois (ces infos apparaissent dans chaque commit) :
git config --global user.name "Camille Martin"
git config --global user.email "camille@example.com"
git config --global init.defaultBranch main
La troisième ligne nomme main la branche principale des nouveaux dépôts (c'est le nom utilisé par GitHub). Pour voir ta configuration : git config --list.
💡 Si tu comptes publier sur GitHub, utilise la même adresse e-mail que ton compte GitHub (ou l'adresse anonyme
...@users.noreply.github.comque GitHub te fournit dans ses réglages).
5.2 Les trois zones de Git¶
C'est LE concept à comprendre. Pense à un photographe qui prépare une photo de groupe :
| Zone | Analogie | Commande pour y envoyer |
|---|---|---|
| Répertoire de travail (working directory) | les gens qui se baladent dans la pièce | tu modifies tes fichiers |
| Zone de préparation (staging area / index) | les gens que tu places devant l'objectif | git add |
Dépôt (repository, dossier .git) |
l'album photo | git commit |
Pourquoi une étape intermédiaire ? Pour choisir ce qui va dans chaque photo. Si tu as corrigé un bug ET commencé une nouvelle fonction, tu peux faire deux commits séparés, chacun avec un message clair.
5.3 Créer un dépôt : git init¶
Git crée un dossier caché .git : c'est là qu'il stocke tout l'historique. Ne le modifie jamais à la main. Supprimer .git = supprimer tout l'historique (tes fichiers restent, mais ne sont plus suivis).
5.4 Observer : git status¶
git status est ta boussole. Lance-la tout le temps, avant et après chaque commande.
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
main.py
nothing added to commit but untracked files present (use "git add" to track)
Git te dit : « je vois deux fichiers, mais je ne les suis pas encore (untracked) ». Et il te dit même quoi faire !
5.5 Préparer : git add¶
git add main.py # un fichier précis
git add src/ # tout un dossier
git add . # tout ce qui a changé dans le dossier courant
Pour retirer un fichier de la zone de préparation (sans perdre tes modifications) :
5.6 Enregistrer : git commit¶
[main (root-commit) b83e225] Premier commit : script de base
2 files changed, 5 insertions(+)
create mode 100644 .gitignore
create mode 100644 main.py
b83e225 est l'identifiant (le hash) du commit, une empreinte unique. Chaque commit connaît son « parent » : l'historique forme une chaîne.
Écrire un bon message de commit :
- court (moins de 70 caractères environ) ;
- à l'impératif ou à l'indicatif, qui décrit ce que fait le commit : « Ajoute le calcul de la moyenne », « Corrige la division par zéro » ;
- ❌ à éviter : « modif », « wip », « ça marche enfin », « azerty ».
Raccourci pour les fichiers déjà suivis : git commit -am "message" fait add + commit d'un coup (mais n'ajoute pas les nouveaux fichiers).
🎯 Quand committer ? Dès que tu as une petite étape qui fonctionne : une fonction terminée, un bug corrigé. Mieux vaut beaucoup de petits commits qu'un énorme commit « tout le projet ».
5.7 Consulter l'historique : git log¶
git log # historique détaillé (q pour quitter)
git log --oneline # une ligne par commit
git log --oneline --graph # avec un dessin des branches
💡
git logs'ouvre dans un afficheur : flèches pour défiler,qpour quitter. Beaucoup de débutants restent coincés ici !
5.8 Voir les différences : git diff¶
git diff # modifications pas encore préparées (non « add »)
git diff --staged # modifications préparées, prêtes à être commitées
git diff b83e225 # différences entre ce commit et maintenant
diff --git a/main.py b/main.py
--- a/main.py
+++ b/main.py
@@ -1 +1,2 @@
-print("Bonjour")
+nom = input("Nom ? ")
+print(f"Bonjour {nom}")
Les lignes en - (rouge) ont été supprimées, celles en + (vert) ajoutées.
5.9 Annuler des choses¶
| Je veux… | Commande |
|---|---|
| annuler mes modifications d'un fichier (revenir au dernier commit) | git restore main.py ⚠️ perte définitive des modifs |
| retirer un fichier de la zone de préparation | git restore --staged main.py |
| voir un ancien fichier sans rien casser | git show b83e225:main.py |
| corriger le message du dernier commit (pas encore publié) | git commit --amend -m "Nouveau message" |
| annuler un commit en créant un commit inverse (sûr, même publié) | git revert 4f5b154 |
⚠️ Tu verras parfois
git reset --hardsur Internet. Cette commande efface du travail sans retour possible. Évite-la tant que tu ne la maîtrises pas.
6. Le fichier .gitignore¶
Certains fichiers ne doivent jamais entrer dans Git :
- le dossier
.venv/(énorme, spécifique à ta machine, se recrée avecrequirements.txt) ; - les caches
__pycache__/et fichiers*.pyc(générés automatiquement par Python) ; - les secrets : mots de passe, clés d'API, fichier
.env; - les fichiers propres à ton système ou ton éditeur (
.DS_Store,Thumbs.db,.vscode/…).
On les liste dans un fichier texte nommé exactement .gitignore, à la racine du projet. Voici un bon point de départ pour Python :
# Environnements virtuels
.venv/
venv/
env/
# Fichiers compilés de Python
__pycache__/
*.py[cod]
# Tests et outils
.pytest_cache/
.ruff_cache/
.coverage
htmlcov/
# Distribution / packaging
build/
dist/
*.egg-info/
# Secrets et réglages locaux
.env
# Éditeurs et systèmes d'exploitation
.vscode/
.idea/
.DS_Store
Thumbs.db
Syntaxe :
dossier/ignore un dossier entier ;*.logignore tous les fichiers finissant par.log;# ...est un commentaire ;!important.logcrée une exception (à ne pas ignorer).
💡 Crée le .gitignore AVANT ton premier commit. GitHub propose aussi un modèle « Python » tout prêt quand tu crées un dépôt.
Pour vérifier pourquoi un fichier est ignoré :
Si tu as déjà commité un fichier par erreur, l'ajouter au .gitignore ne suffit pas : Git continue de le suivre. Il faut le retirer du suivi (sans le supprimer de ton disque) :
git rm -r --cached .venv
echo ".venv/" >> .gitignore
git add .gitignore
git commit -m "Retire .venv du suivi Git"
🔐 Secret commité = secret compromis. Si tu as publié une clé d'API ou un mot de passe sur GitHub, le retirer dans un nouveau commit ne suffit pas : il reste dans l'historique. Change immédiatement ce mot de passe / révoque cette clé.
7. Les branches¶
Une branche est une ligne de développement parallèle. Analogie : tu écris un roman, et tu veux tester une fin alternative. Plutôt que de raturer ton manuscrit, tu fais une photocopie et tu écris la nouvelle fin dessus. Si elle te plaît, tu l'intègres au manuscrit ; sinon, tu jettes la photocopie.
7.1 Créer et changer de branche¶
git branch # liste les branches (* = branche actuelle)
git switch -c ajout-salutation # crée la branche ET s'y place
git switch main # revient sur main
git branch -d ajout-salutation # supprime une branche déjà fusionnée
💡 Dans de vieux tutoriels, tu verras
git checkout -b nomà la place degit switch -c nom: c'est équivalent.switchest plus récent et plus clair.
Quand tu changes de branche, les fichiers de ton dossier changent réellement pour refléter l'état de cette branche. C'est normal ! Pense à committer (ou annuler) tes modifications avant de changer de branche.
7.2 Fusionner : git merge¶
On se place sur la branche qui reçoit les modifications, puis on fusionne :
Si main n'a pas bougé depuis la création de la branche, Git avance simplement le pointeur (fast-forward) :
Updating b83e225..4f5b154
Fast-forward
main.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
Si les deux branches ont avancé, Git crée un commit de fusion qui réunit les deux histoires.
7.3 Résoudre un conflit¶
Un conflit survient quand les deux branches ont modifié la même ligne différemment. Git ne peut pas deviner laquelle garder, il te demande d'arbitrer :
Auto-merging main.py
CONFLICT (content): Merge conflict in main.py
Automatic merge failed; fix conflicts and then commit the result.
Le fichier contient alors des marqueurs :
nom = input("Nom ? ")
<<<<<<< HEAD
print(f"Bienvenue {nom}")
=======
print(f"Salut {nom} !")
>>>>>>> couleur
- entre
<<<<<<< HEADet=======: la version de ta branche actuelle (main) ; - entre
=======et>>>>>>> couleur: la version de la branche fusionnée.
Pour résoudre :
- Ouvre le fichier, choisis la bonne version (ou combine-les), supprime les trois lignes de marqueurs. VS Code affiche des boutons « Accept Current / Accept Incoming / Accept Both » très pratiques.
- Résultat, par exemple :
- Termine la fusion :
Pas de panique : un conflit est une situation normale et sans danger. Si tu veux tout annuler et revenir avant la fusion : git merge --abort.
8. GitHub : publier et collaborer¶
8.1 Créer un compte et un dépôt¶
- Crée un compte gratuit sur github.com.
- Clique sur + (en haut à droite) → New repository.
- Donne un nom (ex.
gestion-taches), une courte description, choisis Public ou Private. - Si ton projet existe déjà en local, ne coche rien (pas de README, pas de .gitignore, pas de licence) : le dépôt doit être vide pour éviter des conflits au premier envoi.
- Clique sur Create repository. GitHub affiche l'adresse du dépôt, par exemple
https://github.com/camille-martin/gestion-taches.git.
8.2 S'authentifier¶
GitHub n'accepte plus ton mot de passe dans le terminal. Trois solutions, de la plus simple à la plus technique :
- GitHub CLI : installe
gh(cli.github.com) puis lancegh auth loginet laisse-toi guider. ✅ Recommandé pour débuter. - Git Credential Manager : inclus dans Git for Windows ; une fenêtre de connexion s'ouvre au premier
push. - Clé SSH : plus technique, très pratique ensuite (voir la documentation GitHub « Connecting to GitHub with SSH »).
8.3 Relier ton dépôt local : git remote¶
Un remote est un dépôt distant, avec un surnom. Par convention, le principal s'appelle origin.
8.4 Envoyer : git push¶
-u (ou --set-upstream) mémorise le lien entre ta branche main locale et celle de GitHub. La première fois seulement. Ensuite, un simple git push suffit.
Rafraîchis la page GitHub : ton code est en ligne ! 🚀
8.5 Récupérer : git pull et git clone¶
git clone: télécharger un dépôt pour la première fois (sur un nouvel ordinateur, ou le projet de quelqu'un d'autre).
git clone https://github.com/camille-martin/gestion-taches.git
cd gestion-taches
python3 -m venv .venv # Windows : py -m venv .venv
source .venv/bin/activate # Windows : .venv\Scripts\Activate.ps1
pip install -r requirements.txt
Remarque : le .venv n'est pas dans le dépôt (grâce au .gitignore), donc on le recrée. C'est exactement pour ça que requirements.txt existe.
git pull: récupérer les nouveaux commits d'un dépôt que tu as déjà (par exemple ceux que tu as poussés depuis un autre ordinateur, ou ceux d'un collègue).
Routine quotidienne quand tu travailles sur plusieurs machines :
8.6 Le README.md¶
Le fichier README.md à la racine est la vitrine de ton projet : GitHub l'affiche automatiquement sous la liste des fichiers. Il est écrit en Markdown (le même format que ce cours). Un bon README répond à : c'est quoi ? comment l'installer ? comment l'utiliser ?
# Gestion de tâches
Petit gestionnaire de tâches en ligne de commande, écrit en Python.
## Fonctionnalités
- Ajouter, lister et cocher des tâches
- Sauvegarde automatique dans un fichier JSON
## Installation
```bash
git clone https://github.com/camille-martin/gestion-taches.git
cd gestion-taches
python3 -m venv .venv
source .venv/bin/activate # Windows : .venv\Scripts\Activate.ps1
pip install -r requirements.txt
```
## Utilisation
```bash
python main.py
```
## Auteur
Camille Martin — projet réalisé en apprenant Python.
8.7 Pour aller plus loin sur GitHub¶
- Issues : liste de bugs et d'idées pour ton projet.
- Pull requests : proposer des modifications (depuis une branche) et les faire relire avant de fusionner. C'est la base du travail en équipe et de la contribution aux projets open source.
- Fork : copier le dépôt de quelqu'un d'autre dans ton compte pour y contribuer.
- Licence : un fichier
LICENSE(MIT, GPL…) indique ce que les autres ont le droit de faire avec ton code.
9. Résumé des commandes¶
| Besoin | Commande |
|---|---|
| Créer un venv | python3 -m venv .venv (Windows : py -m venv .venv) |
| Activer (macOS/Linux) | source .venv/bin/activate |
| Activer (Windows PowerShell) | .venv\Scripts\Activate.ps1 |
| Désactiver | deactivate |
| Installer / désinstaller | pip install x / pip uninstall x |
| Lister | pip list / pip freeze |
| Sauver / restaurer les dépendances | pip freeze > requirements.txt / pip install -r requirements.txt |
| Nouveau dépôt Git | git init |
| État | git status |
| Préparer / enregistrer | git add . / git commit -m "..." |
| Historique / différences | git log --oneline / git diff |
| Branches | git switch -c x / git switch main / git merge x |
| GitHub | git remote add origin URL / git push -u origin main / git pull / git clone URL |
Pièges fréquents¶
1. Oublier d'activer le venv¶
Symptôme : tu as fait pip install requests, mais import requests donne ModuleNotFoundError: No module named 'requests'. Ou l'inverse : le paquet s'installe dans le Python global.
Correction : vérifie que (.venv) apparaît au début de l'invite. Sinon, active le venv (source .venv/bin/activate ou .venv\Scripts\Activate.ps1). Dans VS Code, vérifie aussi l'interpréteur sélectionné (en bas à droite de la fenêtre) : il doit pointer vers .venv.
2. Committer le dossier .venv¶
Symptôme : git status affiche des milliers de fichiers, le push est interminable, et le dépôt GitHub contient un dossier .venv énorme qui ne fonctionne de toute façon pas sur un autre ordinateur.
Correction : ajoute .venv/ au .gitignore, puis retire-le du suivi : git rm -r --cached .venv, et committe. À l'avenir, crée le .gitignore avant le premier git add.
3. Pas de .gitignore (ou mal nommé)¶
Symptôme : __pycache__/ et .pyc apparaissent dans chaque commit ; ou ton fichier s'appelle gitignore.txt / .gitignore.txt et n'a aucun effet.
Correction : le fichier doit s'appeler exactement .gitignore (avec le point, sans extension), et être à la racine du projet. Sous Windows, active « Afficher les extensions de fichiers » dans l'explorateur pour vérifier qu'il n'y a pas de .txt caché.
4. Lancer git init dans le mauvais dossier¶
Symptôme : git status liste tout ton dossier personnel (Documents, Images…), ou tu as un dépôt dans un dépôt.
Correction : vérifie où tu es avec pwd (macOS/Linux) ou Get-Location (PowerShell) avant git init. Pour annuler un git init malencontreux, supprime le dossier .git créé au mauvais endroit (et seulement celui-là !).
5. requirements.txt oublié ou pas à jour¶
Symptôme : le projet fonctionne chez toi, mais chez ton ami (ou après un git clone), on obtient ModuleNotFoundError.
Correction : après chaque pip install d'un nouveau paquet, régénère pip freeze > requirements.txt et committe ce fichier. Teste de temps en temps : supprime .venv, recrée-le, pip install -r requirements.txt, et lance ton programme.
6. Rester coincé dans git log ou dans l'éditeur de commit¶
Symptôme : après git log, le terminal n'accepte plus de commande ; ou après git commit (sans -m), un écran étrange (Vim) s'ouvre.
Correction : dans git log, appuie sur q. Dans Vim : tape ton message après avoir appuyé sur i, puis Échap, puis :wq et Entrée (ou :q! pour abandonner). Pour éviter ça, utilise toujours git commit -m "message", ou configure VS Code comme éditeur : git config --global core.editor "code --wait".
7. Le premier push est refusé¶
Symptôme : ! [rejected] main -> main (fetch first) ou failed to push some refs.
Correction : le dépôt GitHub contient des commits que tu n'as pas (souvent parce que tu as coché « Add a README » à la création). Récupère-les d'abord : git pull origin main --allow-unrelated-histories, résous un éventuel conflit, puis git push. Pour l'éviter : crée le dépôt GitHub vide quand ton projet existe déjà en local.
8. Laisser des marqueurs de conflit dans le code¶
Symptôme : SyntaxError sur une ligne <<<<<<< HEAD après une fusion.
Correction : un conflit n'est résolu que lorsque toutes les lignes <<<<<<<, ======= et >>>>>>> ont disparu. Cherche-les (Ctrl+F sur <<<<<<<), corrige, puis git add et git commit.
Exercices¶
Exercice 1 ⭐ — Premier venv¶
- Crée un dossier
test_venvet ouvre un terminal dedans. - Crée un environnement virtuel
.venvpuis active-le. - Vérifie que tu es dans le venv avec une commande Python d'une ligne.
- Désactive-le, relance la même commande : que constates-tu ?
Écris la suite exacte de commandes pour ton système (et, si tu peux, pour l'autre).
Exercice 2 ⭐ — Suis-je dans un venv ?¶
Écris un script verifier_venv.py qui affiche « ✅ Tu es dans un environnement virtuel » suivi du dossier du venv, ou « ⚠️ Tu utilises le Python global du système » suivi du chemin de l'interpréteur.
Indice : dans un venv, sys.prefix (le dossier du Python en cours) est différent de sys.base_prefix (le dossier du Python d'origine). sys.executable donne le chemin de l'interpréteur.
Lance-le avec et sans venv activé.
Exercice 3 ⭐ — La liste de courses¶
Dans ton venv de l'exercice 1 :
- installe le paquet
rich; - affiche la liste des paquets installés ;
- génère un
requirements.txt; - supprime le venv, recrée-le, et réinstalle tout à partir du
requirements.txt; - vérifie que ça marche avec
python -c "from rich import print; print('[bold green]Ça marche ![/]')".
Exercice 4 ⭐⭐ — Trier le bon grain de l'ivraie¶
Voici le contenu d'un dossier de projet :
calculatrice/
├── .venv/
├── __pycache__/operations.cpython-312.pyc
├── .env (contient API_KEY=abc123)
├── .vscode/settings.json
├── operations.py
├── main.py
├── requirements.txt
├── README.md
├── notes_perso.txt
└── historique.log
- Indique, pour chaque élément, s'il doit être commité ou ignoré, et pourquoi.
- Écris le
.gitignorecorrespondant (on décide que les fichiers.logetnotes_perso.txtsont personnels).
Exercice 5 ⭐⭐ — Trois commits et un retour en arrière¶
- Crée un dossier
journal, initialise un dépôt Git et un.gitignorePython. - Crée
journal.pyqui affiche « Mon journal ». Committe. - Ajoute une ligne qui affiche la date du jour (avec
datetime). Avant de committer, affiche les différences. Committe. - Ajoute une ligne qui affiche « Bonne journée ! ». Committe.
- Affiche l'historique sur une ligne par commit.
- Modifie
journal.pyen y écrivant n'importe quoi, puis annule cette modification avec Git. - Affiche le contenu de
journal.pytel qu'il était au tout premier commit, sans rien modifier.
Exercice 6 ⭐⭐ — Branches et conflit volontaire¶
Dans le dépôt de l'exercice 5 :
- Crée une branche
anglaiset change « Bonne journée ! » en « Have a nice day! ». Committe. - Reviens sur
mainet change « Bonne journée ! » en « Belle journée à toi ! ». Committe. - Fusionne
anglaisdansmain: un conflit apparaît. - Résous-le en gardant les deux phrases, sur deux lignes. Termine la fusion.
- Affiche le graphe de l'historique, puis supprime la branche
anglais.
Exercice 7 ⭐⭐⭐ — Analyseur de requirements.txt¶
Écris un script analyser_requirements.py qui lit un fichier requirements.txt et affiche :
- la liste des paquets épinglés (
nom==version) avec leur version ; - la liste des paquets non épinglés (sans version, ou avec
>=,~=…), accompagnés d'un avertissement.
Le script doit ignorer les lignes vides et les commentaires (ce qui suit un #, y compris en fin de ligne). Écris une fonction analyser_ligne(ligne) qui renvoie un tuple (nom, version) (avec version = None si non épinglé) ou None pour une ligne à ignorer.
Teste avec :
Exercice 8 ⭐⭐⭐ — Générateur de projet¶
Écris un script nouveau_projet.py qui, lancé avec python nouveau_projet.py mon_projet :
- crée le dossier
mon_projet(et s'arrête avec un message d'erreur s'il existe déjà) ; - y écrit un
.gitignorePython, unREADME.md(titre = nom du projet), unrequirements.txtvide et unmain.pyminimal avecif __name__ == "__main__":; - crée un venv
.venvdans ce dossier ; - initialise un dépôt Git et fait un premier commit « Initialisation du projet ».
Indices : pathlib.Path pour les fichiers (chapitre 07), sys.argv pour les arguments, et subprocess.run([...], cwd=dossier, check=True) pour lancer une commande dans un dossier donné. sys.executable est le chemin du Python en cours.
Mini-projet¶
🚀 Publier un de tes projets sur GitHub¶
Tu as écrit plusieurs programmes depuis le début du cours : un jeu de devinette, un gestionnaire de contacts, un carnet de notes en JSON (chapitre 07), des classes (chapitre 10)… Il est temps d'en choisir un et de lui donner une vraie vie de projet : versionné, documenté, publié.
Cahier des charges¶
Ton projet publié doit :
- avoir son propre dossier avec un environnement virtuel
.venv; - contenir un
requirements.txtà jour (même s'il est vide parce que tu n'utilises que la bibliothèque standard — dans ce cas, écris-y un commentaire# Aucune dépendance externe) ; - contenir un
.gitignorePython complet ; - contenir un
README.mdavec : titre, description, fonctionnalités, installation, utilisation, auteur ; - avoir au moins 4 commits avec des messages clairs (pas un seul commit géant) ;
- avoir utilisé au moins une branche fusionnée dans
mainpour ajouter une fonctionnalité ou une amélioration ; - être publié sur GitHub ;
- être clonable et exécutable : un
git clonedans un autre dossier, suivi de l'installation décrite dans le README, doit permettre de lancer le programme.
Étapes suggérées¶
- Choisir et ranger : copie ton projet dans un nouveau dossier (ex.
~/projets/carnet-notes). Supprime les fichiers inutiles. - Environnement : crée et active le venv, installe les éventuelles dépendances, génère
requirements.txt. - Git : crée le
.gitignore,git init, vérifie avecgit statusque.venvn'apparaît pas, premier commit. - README : rédige-le, committe-le séparément.
- Branche : crée une branche
amelioration, ajoute une petite fonctionnalité (un message d'accueil, une option de menu, une validation de saisie…), committe, fusionne dansmain. - GitHub : crée le dépôt vide, ajoute le remote, pousse.
- Test de vérité : dans un autre dossier,
git clone, recrée le venv, installe, lance. Si quelque chose manque, corrige, committe et pousse à nouveau.
Pistes d'amélioration¶
- Ajoute un fichier
LICENSE(GitHub propose « Add file → Create new file » puis un modèle de licence MIT). - Ajoute une capture d'écran ou un exemple de sortie du terminal dans le README.
- Crée deux ou trois issues sur GitHub pour noter tes idées d'améliorations, puis ferme-les avec un commit contenant
Closes #1dans le message. - Travaille depuis un deuxième ordinateur (ou un deuxième dossier) et entraîne-toi au cycle
pull→ modifier →push. - Remplace
requirements.txtpar unpyproject.tomlet essaieuv.
Corrigés¶
Corrigé de l'exercice 1
**macOS / Linux :** **Windows PowerShell :** **Constat** : venv activé, `sys.prefix` pointe vers le dossier `.venv` ; une fois désactivé, il pointe vers l'installation globale de Python. C'est la preuve que l'activation change le Python utilisé. Note aussi que dans le venv, `python` suffit, alors qu'en dehors on écrit `python3` (macOS/Linux) ou `py` (Windows).Corrigé de l'exercice 2
import sys
def est_dans_un_venv() -> bool:
"""Renvoie True si le script tourne dans un environnement virtuel."""
return sys.prefix != sys.base_prefix
if est_dans_un_venv():
print("✅ Tu es dans un environnement virtuel.")
print(f" Dossier du venv : {sys.prefix}")
else:
print("⚠️ Tu utilises le Python global du système.")
print(f" Python utilisé : {sys.executable}")
Corrigé de l'exercice 3
# (venv activé)
pip install rich
pip list
pip freeze > requirements.txt
cat requirements.txt # Windows PowerShell : Get-Content requirements.txt
deactivate
rm -rf .venv # Windows : Remove-Item -Recurse -Force .venv
python3 -m venv .venv # Windows : py -m venv .venv
source .venv/bin/activate # Windows : .venv\Scripts\Activate.ps1
pip install -r requirements.txt
python -c "from rich import print; print('[bold green]Ça marche ![/]')"
Corrigé de l'exercice 4
| Élément | Décision | Raison | |---|---|---| | `.venv/` | ❌ ignorer | lourd, spécifique à la machine, se recrée avec `requirements.txt` | | `__pycache__/` | ❌ ignorer | généré automatiquement par Python | | `.env` | ❌ ignorer | **contient un secret** (clé d'API) | | `.vscode/` | ❌ ignorer | réglages personnels de l'éditeur | | `operations.py`, `main.py` | ✅ commiter | c'est le code du projet | | `requirements.txt` | ✅ commiter | indispensable pour réinstaller les dépendances | | `README.md` | ✅ commiter | documentation du projet | | `notes_perso.txt` | ❌ ignorer | personnel (décision de l'énoncé) | | `historique.log` | ❌ ignorer | fichier généré à l'exécution | Pour vérifier : `git status` ne doit plus montrer que `operations.py`, `main.py`, `requirements.txt`, `README.md` et `.gitignore`. **Bonne pratique** : fournis un fichier `.env.example` (commité) qui contient `API_KEY=ta_cle_ici`, pour indiquer aux autres quelles variables définir sans divulguer les tiennes.Corrigé de l'exercice 5
mkdir journal && cd journal
git init
printf '.venv/\n__pycache__/\n*.pyc\n.env\n' > .gitignore # ou crée-le dans VS Code
Corrigé de l'exercice 6
git switch -c anglais
# dans journal.py : "Bonne journée !" → "Have a nice day!"
git commit -am "Traduit le message de fin en anglais"
git switch main
# dans journal.py : "Bonne journée !" → "Belle journée à toi !"
git commit -am "Reformule le message de fin"
git merge anglais
Auto-merging journal.py
CONFLICT (content): Merge conflict in journal.py
Automatic merge failed; fix conflicts and then commit the result.
Corrigé de l'exercice 7
from pathlib import Path
def analyser_ligne(ligne: str) -> tuple[str, str | None] | None:
"""Analyse une ligne de requirements.txt.
Renvoie (nom, version) ou None si la ligne est vide ou un commentaire.
version vaut None si le paquet n'est pas épinglé avec ==.
"""
ligne = ligne.split("#", 1)[0].strip() # retire les commentaires
if not ligne:
return None
if "==" in ligne:
nom, version = ligne.split("==", 1)
return nom.strip(), version.strip()
# >=, <=, ~= ou rien du tout : on récupère juste le nom
for separateur in (">=", "<=", "~=", ">", "<"):
if separateur in ligne:
return ligne.split(separateur, 1)[0].strip(), None
return ligne, None
def analyser_fichier(chemin: Path) -> None:
epingles = []
non_epingles = []
for ligne in chemin.read_text(encoding="utf-8").splitlines():
resultat = analyser_ligne(ligne)
if resultat is None:
continue
nom, version = resultat
if version is None:
non_epingles.append(nom)
else:
epingles.append(f"{nom} ({version})")
print(f"Paquets épinglés ({len(epingles)}) :")
for paquet in epingles:
print(f" - {paquet}")
print(f"Paquets NON épinglés ({len(non_epingles)}) :")
for nom in non_epingles:
print(f" - {nom} ⚠️ version libre")
if __name__ == "__main__":
analyser_fichier(Path("requirements.txt"))
Corrigé de l'exercice 8
"""Crée le squelette d'un nouveau projet Python prêt pour Git.
Usage : python nouveau_projet.py nom_du_projet
"""
import subprocess
import sys
from pathlib import Path
GITIGNORE = """\
# Environnements virtuels
.venv/
venv/
# Fichiers compilés de Python
__pycache__/
*.pyc
# Secrets et réglages locaux
.env
# Éditeurs et système
.vscode/
.idea/
.DS_Store
Thumbs.db
"""
def creer_projet(nom: str) -> Path:
dossier = Path(nom)
if dossier.exists():
raise SystemExit(f"Erreur : le dossier « {nom} » existe déjà.")
dossier.mkdir()
(dossier / ".gitignore").write_text(GITIGNORE, encoding="utf-8")
(dossier / "README.md").write_text(
f"# {nom}\n\nDescription du projet.\n", encoding="utf-8"
)
(dossier / "requirements.txt").write_text("", encoding="utf-8")
(dossier / "main.py").write_text(
'def main():\n print("Bonjour !")\n\n\n'
'if __name__ == "__main__":\n main()\n',
encoding="utf-8",
)
# sys.executable = le Python qui exécute ce script
subprocess.run([sys.executable, "-m", "venv", ".venv"], cwd=dossier, check=True)
subprocess.run(["git", "init"], cwd=dossier, check=True)
subprocess.run(["git", "add", "."], cwd=dossier, check=True)
subprocess.run(
["git", "commit", "-m", "Initialisation du projet"], cwd=dossier, check=True
)
return dossier
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage : python nouveau_projet.py nom_du_projet")
sys.exit(1)
chemin = creer_projet(sys.argv[1])
print(f"Projet créé dans {chemin.resolve()}")
Corrigé du mini-projet
Exemple avec un carnet de notes (`carnet-notes`). Les commandes sont pour macOS/Linux ; les variantes Windows sont en commentaire. **1–2. Dossier et environnement**mkdir -p ~/projets/carnet-notes && cd ~/projets/carnet-notes
# (copie ici tes fichiers : main.py, carnet.py…)
python3 -m venv .venv # Windows : py -m venv .venv
source .venv/bin/activate # Windows : .venv\Scripts\Activate.ps1
# Si le projet n'a aucune dépendance externe :
echo "# Aucune dépendance externe" > requirements.txt
# Sinon : pip install ... puis pip freeze > requirements.txt
git init
git status # .venv NE doit PAS apparaître
git add .
git commit -m "Version initiale du carnet de notes"
git switch -c validation-saisie
# … code : refuser une note hors de [0, 20] avec un message clair …
python main.py # on teste !
git commit -am "Valide les notes saisies entre 0 et 20"
# … une deuxième petite amélioration …
git commit -am "Affiche la moyenne avec deux décimales"
git switch main
git merge validation-saisie
git branch -d validation-saisie
git log --oneline --graph # au moins 4 commits
Récapitulatif¶
Points clés à retenir :
- Un venv est un dossier
.venvqui isole les bibliothèques d'un projet. Un projet = un venv. - Création :
python3 -m venv .venv(Windows :py -m venv .venv). Activation :source .venv/bin/activate(macOS/Linux) ou.venv\Scripts\Activate.ps1(Windows). Sortie :deactivate. - pip installe depuis PyPI :
install,uninstall,list,show,freeze. - requirements.txt liste les dépendances :
pip freeze > requirements.txtpour l'écrire,pip install -r requirements.txtpour tout réinstaller. - pyproject.toml est le format de configuration moderne ; uv est un outil rapide qui regroupe venv + pip.
- Git enregistre des photos (commits) du projet : modifier →
git add→git commit -m.git statusest ta boussole. git log --oneline,git diff,git restorepermettent de consulter et d'annuler.- Le .gitignore exclut
.venv/,__pycache__/,.env… et se crée avant le premier commit. - Les branches (
git switch -c,git merge) permettent d'expérimenter sans risque ; un conflit se résout à la main, puisadd+commit. - GitHub héberge tes dépôts :
git remote add origin,git push -u origin main,git pull,git clone. Le README.md est la vitrine du projet.
Checklist :
- Je sais créer, activer (sur mon système) et désactiver un venv.
- Je vérifie la présence de
(.venv)avant chaquepip install. - Je sais générer et utiliser un
requirements.txt. - J'ai configuré mon nom et mon e-mail dans Git.
- Je connais le cycle
status→add→commitet j'écris des messages clairs. - J'ai un
.gitignorePython dans chacun de mes projets. - Je sais créer une branche, la fusionner et résoudre un conflit simple.
- J'ai publié au moins un projet sur GitHub, avec un README.
- Je sais cloner un projet et le faire fonctionner grâce à son README.