Aller au contenu principal

Lecture et Écriture de Fichiers

La gestion des fichiers est une compétence essentielle : lire des configurations, écrire des logs, traiter des CSV ou échanger des données JSON sont des tâches quotidiennes du développeur.


1. Ouvrir un fichier — open()

La fonction open() prend deux arguments principaux : le chemin du fichier et le mode d'ouverture.

ModeDescription
'r'Lecture (défaut) — erreur si le fichier n'existe pas
'w'Écriture — crée ou écrase le fichier
'a'Ajout (append) — crée ou écrit à la fin
'x'Création exclusive — erreur si le fichier existe déjà
'rb'Lecture en mode binaire
'wb'Écriture en mode binaire
# Ouverture et fermeture manuelle — à éviter !
f = open("data.txt", "r")
contenu = f.read()
f.close() # Oublie facilement !

Le gestionnaire de contexte with — toujours utiliser !

Le bloc with garantit que le fichier est fermé automatiquement, même en cas d'exception.

# Bonne pratique : toujours utiliser with
with open("data.txt", "r", encoding="utf-8") as f:
contenu = f.read()
# Le fichier est fermé automatiquement ici
Encoding

Spécifiez toujours encoding="utf-8" pour éviter les surprises sur Windows ou avec des caractères accentués.


2. Lire un fichier

Lire tout le contenu

with open("notes.txt", "r", encoding="utf-8") as f:
contenu = f.read()
print(contenu)

Lire ligne par ligne

# Lire une seule ligne
with open("notes.txt", "r", encoding="utf-8") as f:
premiere_ligne = f.readline()
print(premiere_ligne)

# Lire toutes les lignes dans une liste
with open("notes.txt", "r", encoding="utf-8") as f:
lignes = f.readlines()
print(lignes) # [' ligne1\n', 'ligne2\n', ...]

# Itérer ligne par ligne — le plus efficace pour les grands fichiers
with open("notes.txt", "r", encoding="utf-8") as f:
for ligne in f:
print(ligne.strip()) # .strip() supprime les \n

Exercice 1 — Lire un fichier avec le gestionnaire de contexte

Bonne pratique - Toujours with

N'ouvrez jamais un fichier sans le gestionnaire de contexte with. Il garantit la fermeture du fichier et la libération des ressources, même si une exception survient.


3. Écrire dans un fichier

write() et writelines()

# Écrire une chaîne
with open("sortie.txt", "w", encoding="utf-8") as f:
f.write("Première ligne\n")
f.write("Deuxième ligne\n")

# Ecrire une liste de chaines
lignes = ["Alice\n", "Bob\n", "Charlie\n"]
with open("noms.txt", "w", encoding="utf-8") as f:
f.writelines(lignes)
Les retours à la ligne

write() n'ajoute pas de \n automatiquement. Vous devez les inclure manuellement dans vos chaînes.

# Pratique courante : joindre avec des sauts de ligne
noms = ["Alice", "Bob", "Charlie"]
with open("noms.txt", "w", encoding="utf-8") as f:
f.write("\n".join(noms))

Exercice 2 — Écrire des lignes dans un fichier

Bonne pratique - writelines vs write + join

f.writelines(liste) n'ajoute pas de séparateur. Privilégiez f.write("\n".join(liste)) pour écrire une liste avec un élément par ligne, c'est plus explicite.


4. Mode ajout (append)

Le mode 'a' écrit à la fin du fichier sans effacer le contenu existant.

# Ajouter une entrée de log
with open("app.log", "a", encoding="utf-8") as f:
f.write("2024-01-15 10:30:00 - Connexion utilisateur Alice\n")

Exercice 3 — Ajouter du texte à un fichier existant

Bonne pratique - Logs avec append

Pour les fichiers de log ou d'historique, utilisez toujours le mode 'a'. Le mode 'w' écraserait toutes les entrées précédentes !


5. Chemins de fichiers

os.path — approche classique

import os

# Construire un chemin de façon portable (Windows/Linux/Mac)
chemin = os.path.join("dossier", "sous_dossier", "fichier.txt")
print(chemin) # dossier/sous_dossier/fichier.txt

# Vérifier l'existence
if os.path.exists(chemin):
print("Le fichier existe")

# Obtenir le dossier parent
dossier = os.path.dirname("/home/user/projet/main.py")
print(dossier) # /home/user/projet

# Nom du fichier seul
nom = os.path.basename("/home/user/projet/main.py")
print(nom) # main.py

pathlib.Path — approche moderne (recommandée)

from pathlib import Path

# Construction avec /
chemin = Path("data") / "fichiers" / "config.txt"
print(chemin) # data/fichiers/config.txt

# Verifications
print(chemin.exists()) # True/False
print(chemin.is_file()) # True/False
print(chemin.suffix) # .txt

# Lecture et écriture directes
texte = Path("notes.txt").read_text(encoding="utf-8")
Path("sortie.txt").write_text("Bonjour !", encoding="utf-8")

# Lister les fichiers d'un dossier
for f in Path(".").glob("*.txt"):
print(f)

# Creer un dossier (et ses parents)
Path("data/exports").mkdir(parents=True, exist_ok=True)

6. Fichiers CSV

Le module csv simplifie la lecture et l'écriture de fichiers CSV.

Lire un CSV

import csv

# Lecture simple
with open("etudiants.csv", "r", encoding="utf-8", newline="") as f:
lecteur = csv.reader(f)
next(lecteur) # Sauter l'en-tête
for ligne in lecteur:
print(ligne) # ['Alice', '22', '16.5']

# Lecture avec DictReader — chaque ligne est un dict
with open("etudiants.csv", "r", encoding="utf-8", newline="") as f:
lecteur = csv.DictReader(f)
for ligne in lecteur:
print(f"Nom: {ligne['nom']}, Note: {ligne['note']}")

Écrire un CSV

import csv

donnees = [
{"nom": "Alice", "age": 22, "note": 16.5},
{"nom": "Bob", "age": 24, "note": 14.0},
]

with open("resultats.csv", "w", encoding="utf-8", newline="") as f:
champs = ["nom", "age", "note"]
ecrivain = csv.DictWriter(f, fieldnames=champs)
ecrivain.writeheader()
ecrivain.writerows(donnees)

Exercice 4 — Lire un CSV avec DictReader

Bonne pratique - DictReader vs reader

Préférez csv.DictReader à csv.reader : accéder à ligne['nom'] est beaucoup plus lisible et robuste que ligne[0]. Si les colonnes changent d'ordre, votre code reste correct.


7. Fichiers JSON

Le module json permet de lire et écrire des fichiers JSON, format très répandu pour les API et les configurations.

import json

# Dict Python -> JSON dans un fichier
config = {
"version": "1.0",
"debug": False,
"serveurs": ["app1.example.com", "app2.example.com"],
}

with open("config.json", "w", encoding="utf-8") as f:
json.dump(config, f, indent=2, ensure_ascii=False)

# JSON depuis un fichier -> Dict Python
with open("config.json", "r", encoding="utf-8") as f:
data = json.load(f)
print(data["version"]) # 1.0

# Chaine JSON <-> Dict (sans fichier)
chaine = json.dumps({"nom": "Alice"}, indent=2)
dico = json.loads('{"age": 30}')
FonctionDirection
json.dump(data, f)Dict → fichier JSON
json.load(f)Fichier JSON → Dict
json.dumps(data)Dict → chaîne JSON
json.loads(s)Chaîne JSON → Dict

Exercice 5 — Écrire un dictionnaire en JSON

Bonne pratique - ensure_ascii=False

Utilisez toujours ensure_ascii=False avec json.dump() pour que les caractères accentués français soient écrits directement (Alice) plutôt qu'en séquences d'échappement Unicode (é).


Exercice 6 — Lire un fichier JSON

Bonne pratique - json.load vs json.loads

json.load(f) lit depuis un objet fichier ouvert, json.loads(s) parse une chaîne de caractères. Ne les confondez pas : l'un prend un fichier, l'autre une chaîne.


Récapitulatif

# Lire un fichier texte
with open("fichier.txt", "r", encoding="utf-8") as f:
contenu = f.read()

# Ecrire dans un fichier
with open("sortie.txt", "w", encoding="utf-8") as f:
f.write("Contenu\n")

# Ajouter a la fin
with open("log.txt", "a", encoding="utf-8") as f:
f.write("Nouvelle ligne\n")

# Lire un CSV
import csv
with open("data.csv", "r", encoding="utf-8", newline="") as f:
for ligne in csv.DictReader(f):
print(ligne)

# Lire un JSON
import json
with open("config.json", "r", encoding="utf-8") as f:
data = json.load(f)

# Chemin avec pathlib
from pathlib import Path
chemin = Path("dossier") / "fichier.txt"
texte = chemin.read_text(encoding="utf-8")

Quiz de révision


Quel mode ouvre un fichier en écriture sans effacer son contenu existant ?


Pourquoi utiliser with open(...) as f: ?


Quelle fonction du module json lit un fichier JSON et retourne un dictionnaire Python ?


Pourquoi privilégier csv.DictReader plutôt que csv.reader ?


Comment construire un chemin de fichier de façon portable avec pathlib ?


📌 Une solution