Fichiers et dossiers avec pathlib
Automatiser, c’est d’abord confier à Python les manipulations de fichiers répétitives : ranger des exports, renommer des rapports, fusionner des fichiers du mois. Le module standard pathlib rend ces opérations simples et portables.
Des chemins portables
from pathlib import Path
dossier = Path("rapports") / "2026" # l'opérateur / assemble les morceaux
fichier = dossier / "ventes_novembre.csv"
print(fichier) # rapports/2026/ventes_novembre.csv (ou avec \ sous Windows)
print(fichier.name) # ventes_novembre.csv
print(fichier.stem) # ventes_novembre
print(fichier.suffix) # .csv
print(fichier.parent) # rapports/2026
print(fichier.with_suffix(".xlsx").name) # ventes_novembre.xlsx
Path.cwd() # dossier de travail actuel
Path.home() # dossier personnel de l'utilisateur
Plus besoin de concaténer des chaînes avec "/" ou "\\" : pathlib choisit le bon séparateur selon le système.
Lire et écrire du texte
notes = Path("notes.txt")
notes.write_text("Première ligne\nDeuxième ligne\n", encoding="utf-8")
contenu = notes.read_text(encoding="utf-8")
print(contenu.splitlines()) # ['Première ligne', 'Deuxième ligne']
# Pour lire ou écrire au fil de l'eau, ligne par ligne :
with notes.open("a", encoding="utf-8") as f: # "a" : ajout en fin de fichier
f.write("Troisième ligne\n")
with notes.open(encoding="utf-8") as f: # lecture par défaut ("r")
for ligne in f:
print(ligne.rstrip("\n"))
Le bloc with ferme le fichier automatiquement, même en cas d’erreur. Précisez toujours encoding="utf-8" : avant Python 3.15, l’encodage par défaut dépend du système (souvent différent sous Windows), source classique de caractères accentués illisibles. Python 3.15 utilise UTF-8 par défaut partout, mais l’indiquer reste la règle : l’intention est explicite et le code se comporte de la même façon avec les versions précédentes. Les modes : "r" lire, "w" écrire (écrase !), "a" ajouter, "x" créer (erreur si le fichier existe).
Parcourir un dossier
exports = Path("exports")
for chemin in sorted(exports.glob("*.csv")): # fichiers .csv du dossier
print(chemin.name, chemin.stat().st_size, "octets")
tous = list(exports.rglob("*.csv")) # rglob : aussi dans les sous-dossiers
dossiers = [p for p in exports.iterdir() if p.is_dir()]
Créer, déplacer, organiser
archive = Path("archive") / "2026-11"
archive.mkdir(parents=True, exist_ok=True) # crée aussi les parents, pas d'erreur si existe
for chemin in Path("exports").glob("*.csv"):
destination = archive / chemin.name
chemin.replace(destination) # déplace (et écrase si la cible existe)
chemin.unlink() supprime un fichier ; pour un dossier non vide, le module shutil propose shutil.rmtree et shutil.copy2 pour copier. Prudence : une boucle de suppression ou de déplacement agit sur des centaines de fichiers en une seconde. Testez toujours votre script sur un dossier temporaire :
import tempfile
with tempfile.TemporaryDirectory() as tmp:
base = Path(tmp)
(base / "essai.csv").write_text("a,b\n1,2\n", encoding="utf-8")
print([p.name for p in base.iterdir()])
# le dossier temporaire et son contenu sont supprimés à la sortie du bloc
C’est exactement ce que font les exercices de cette leçon.
À retenir
Path+/pour des chemins portables ;name,stem,suffix,parent.read_text/write_textouwith open(...), toujours avecencoding="utf-8".glob,mkdir(parents=True, exist_ok=True),replace; tester sur un dossier temporaire.
Exercices
Les solutions et les tests restent sur le serveur. Dans l'espace étudiant, ton code est exécuté et corrigé, et le tuteur donne des indices avant la solution.
Décomposer et construire des chemins
À partir de
source, calculez :nom: le nom du fichier avec extension ;base: le nom sans extension ;extension: l’extension (avec le point) ;sortie: unPathvers le même nom en.xlsx, placé dans le sous-dossierrapportsdu dossier parent desource.
from pathlib import Path source = Path("donnees") / "2026" / "ventes_novembre.csv" nom = ... base = ... extension = ... sortie = ...Fusionner les fichiers texte d'un dossier
Écrivez
fusionner(dossier, motif="*.txt")qui lit, dans l’ordre alphabétique des noms, tous les fichiers du dossier correspondant au motif, et renvoie la liste de toutes leurs lignes non vides (sans le saut de ligne). Écrivez aussiecrire_lignes(chemin, lignes)qui écrit les lignes dans un fichier UTF-8, une par ligne, en créant au besoin les dossiers parents.Le code de test crée un dossier temporaire ; ne touchez pas au disque en dehors.
from pathlib import Path def fusionner(dossier, motif="*.txt"): ... def ecrire_lignes(chemin, lignes): ...Mode d'ouverture
Vous voulez ajouter une ligne à la fin d’un journal existant sans effacer son contenu. Quel mode utiliser ?
- "w"
- "a"
- "r"
- "x"
Quiz de fin de leçon
Que vaut
Path("a/rapport.final.csv").suffix?- ".final.csv"
- ".csv"
- "csv"
Pourquoi utiliser
with open(...) as f:?- C'est plus rapide
- Le fichier est fermé automatiquement, même en cas d'erreur
- C'est obligatoire pour lire
Que fait
Path("out/2026").mkdir(parents=True, exist_ok=True)si le dossier existe déjà ?- Lève une erreur
- Ne fait rien, sans erreur
- Vide le dossier
La suite du cours
- Lire et écrire du CSV et du JSON20 min
- Automatiser Excel avec pandas et openpyxl20 min
- Interroger une API web20 min
- Un script automatisé de bout en bout20 min