Aller au contenu principal

Lecture et Ecriture de Fichiers

La gestion des fichiers est une competence essentielle : lire des configurations, ecrire des logs, traiter des CSV ou echanger des donnees JSON sont des taches quotidiennes du developpeur.


1. Ouvrir un fichier — open()

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

ModeDescription
'r'Lecture (defaut) — erreur si le fichier n'existe pas
'w'Ecriture — cree ou ecrase le fichier
'a'Ajout (append) — cree ou ecrit a la fin
'x'Creation exclusive — erreur si le fichier existe deja
'rb'Lecture en mode binaire
'wb'Ecriture en mode binaire
# Ouverture et fermeture manuelle — a eviter !
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 ferme automatiquement, meme 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 ferme automatiquement ici
Encoding

Specifiez toujours encoding="utf-8" pour eviter les surprises sur Windows ou avec des caracteres accentues.


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', ...]

# Iterer 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 liberation des ressources, meme si une exception survient.


3. Ecrire dans un fichier

write() et writelines()

# Ecrire une chaine
with open("sortie.txt", "w", encoding="utf-8") as f:
f.write("Premiere ligne\n")
f.write("Deuxieme 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 a la ligne

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

# 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 — Ecrire des lignes dans un fichier

Bonne pratique - writelines vs write + join

f.writelines(liste) n'ajoute pas de separateur. Privilegiez f.write("\n".join(liste)) pour ecrire une liste avec un element par ligne, c'est plus explicite.


4. Mode ajout (append)

Le mode 'a' ecrit a la fin du fichier sans effacer le contenu existant.

# Ajouter une entree 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 a un fichier existant

Bonne pratique - Logs avec append

Pour les fichiers de log ou d'historique, utilisez toujours le mode 'a'. Le mode 'w' ecraserait toutes les entrees precedentes !


5. Chemins de fichiers

os.path — approche classique

import os

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

# Verifier 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 (recommandee)

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 ecriture 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'ecriture 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-tete
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']}")

Ecrire 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

Preferez csv.DictReader a csv.reader : acceder a 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 ecrire des fichiers JSON, format tres repandu 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 → chaine JSON
json.loads(s)Chaine JSON → Dict

Exercice 5 — Ecrire un dictionnaire en JSON

Bonne pratique - ensure_ascii=False

Utilisez toujours ensure_ascii=False avec json.dump() pour que les caracteres accentues francais soient ecrits directement (Alice) plutot qu'en sequences d'echappement 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 chaine de caracteres. Ne les confondez pas : l'un prend un fichier, l'autre une chaine.


Recapitulatif

# 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 revision


Quel mode ouvre un fichier en ecriture 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 privilegier csv.DictReader plutot que csv.reader ?


Comment construire un chemin de fichier de facon portable avec pathlib ?


Une solution