Apprenez en lisant dans l'ordre

Entrées/sorties fichier — Lire et écrire en sécurité avec with open()

Apprends les E/S fichier en Python. Fermeture auto avec with open(), différences entre read / readlines / readline, modes w / a, et le pattern lire-traiter-écrire qui sauvegarde dans un fichier séparé — pratique inclus.

La plupart des données que les programmes manipulent vivent sur le disque sous forme de fichiers. Lire une liste de tâches, ajouter à un log, charger une config — toutes ces opérations sont quotidiennes.

En Python, with open() te permet de faire ça dans une unité syntaxique sûre. Cet article couvre la forme de base de with open(), les trois méthodes de lecture (read / readlines / readline), l'écriture (w) et l'ajout (a), et la gestion des chemins avec dossiers — en exécutant vraiment du code contre des fichiers.

with open() ouvre et ferme les fichiers en sécurité

Ouvrir un fichier est une opération qui fait tenir une ressource par l'OS, et une fois ouvert, tu dois le fermer. Oublier provoque l'épuisement des descripteurs de fichier, ou les données d'écriture restent coincées dans des buffers et n'atteignent jamais le disque.

Ouvrir prend une ressource OS — fermer est le contrat
open()L'OS alloueun FDread / writeclose()libèreopen()L'OS alloueun FDread / writeoubli de close-> FD épuisé+ buffers non vidésnormal
open() fait allouer un descripteur de fichier (FD) par l'OS. Jusqu'à close(), le FD reste pris et les écritures restent en buffer, non vidées. Oublier de fermer est une fuite de ressource sérieuse.

C'est quoi un descripteur de fichier (FD) ?

FD (file descriptor) est l'ID entier que l'OS attribue à chaque fichier actuellement ouvert. Chaque open() distribue un nouveau FD ; close() le rend à l'OS. L'OS définit une limite supérieure par processus (le défaut Linux tourne autour de 1024). Atteins cette limite et les nouveaux open() commencent à échouer avec OSError: Too many open files. Le danger d'oublier de fermer, c'est exactement ça : tenir une ressource finie pour toujours.

Écris la forme with open(path, mode) as f: et le fichier se ferme automatiquement au moment où tu sors du bloc, donc l'erreur est impossible à faire. Le f dans as f est la variable qui reçoit l'objet fichier ; à l'intérieur du bloc with, tu lis et écris à travers f.

Les chemins utilisent des slashs / pour séparer les dossiers. open("data/tasks.txt", "r") ouvre tasks.txt dans le dossier data sous le répertoire courant. Même sur Windows, la convention Python utilise / — en interne, c'est traduit selon l'OS.

Flux de with open()
with open(path, mode)lieras fappeler f.read()ou f.write()closeautole bloc sort
Entrer dans le with ouvre le fichier et le lie à as f. Sortir du bloc — normalement ou via une exception — close() tourne automatiquement.

Lecture — read / readlines / readline

Pour lire un fichier, utilise r (read) comme deuxième argument de open(path, "r"). L'objet fichier renvoyé a trois méthodes de lecture pour différents besoins.

- f.read() — lit tout le fichier comme une seule chaîne.

- f.readlines() — le lit comme une liste de lignes (chaînes).

- f.readline() — lit une ligne. Les appels répétés avancent à la ligne suivante ; une chaîne vide "" signale la fin du fichier.

Ce que retournent les trois méthodes de lecture
f.read()f.readlines()f.readline()une strtexte completliste delignesune str(appel suivant =ligne suivante)
read retourne une chaîne, readlines retourne une liste, readline retourne une chaîne par appel. Choisis selon la taille des données.
# Récupérer tout le fichier comme une seule chaîne
with open("data/tasks.txt", "r") as f:
    content = f.read()
print(type(content))     # <class 'str'>

# Récupérer une liste de lignes
with open("data/tasks.txt", "r") as f:
    lines = f.readlines()
print(type(lines))       # <class 'list'>

# Récupérer une ligne à la fois (appel suivant -> ligne suivante)
with open("data/tasks.txt", "r") as f:
    first  = f.readline()   # "Rédiger le rapport\n"
    second = f.readline()   # "Répondre aux emails\n"

À partir d'ici, la console tourne sur un système de fichiers virtuel (VFS) côté navigateur

La console à droite est un système de fichiers virtuel dans le navigateur — des fichiers comme data/tasks.txt sont pré-installés pour toi. Pour exécuter le même code sur ton PC local, crée un dossier data/ à côté de ton fichier Python (par ex. main.py) et place tasks.txt dedans avant d'exécuter. La syntaxe de chemin ("data/tasks.txt" avec /) est identique au vrai Python.

Clique sur le bouton 📂 Files en haut de la console à droite, et tu verras les deux fichiers pré-installés data/tasks.txt (4 tâches) et data/log.txt (3 lignes d'historique).

① Utilise with open("data/tasks.txt", "r") as f: pour ouvrir le fichier en mode lecture.

② Lis tout avec f.read() et stocke-le dans content.

③ Affiche-le avec print(content).

(Une fois que ça tourne correctement, l'explication apparaîtra.)

Éditeur Python

Exécuter le code pour voir le résultat

Quand le fichier est un enregistrement par ligne (CSV sans en-tête, liste séparée par sauts de ligne, lignes de log), f.readlines() est pratique. Il retourne une liste de chaînes, une par ligne, et chaque élément garde son \n final.

L'imprimer directement produit un double interligne, donc le pattern standard est d'appliquer .rstrip("\n") pour retirer le saut de ligne final.

Utilise data/log.txt (3 lignes d'historique). Lis-le comme une liste avec readlines() et imprime chaque ligne numérotée. C'est le pattern typique pour les vues de log et le formatage de rapports d'ops.

① Ouvre avec with open("data/log.txt", "r") as f: et stocke f.readlines() dans lines.

② Boucle avec enumerate(lines, start=1) pour commencer la numérotation à 1.

③ Retire le saut de ligne final avec .rstrip() et imprime sous forme de f"{n}: {body}".

Éditeur Python

Exécuter le code pour voir le résultat

Gros fichiers ? Lire ligne par ligne — readline et walrus

f.read() et f.readlines() chargent tout le fichier en mémoire. Ça va pour les fichiers taille config, mais un log serveur de plusieurs Go peut planter le programme en épuisant la mémoire.

f.readline() charge une seule ligne à la fois, donc l'usage mémoire reste à une ligne de coût. Quand readline() atteint la fin du fichier, il retourne la chaîne vide "", que tu utilises comme condition de sortie de la boucle.

readline() lit une ligne à la fois
fichier(plusieurs Go)readline()-> ligne 1mémoire :ligne 1(suite)readline()-> ligne 2mémoire :ligne 2EOF atteintreadline()-> ""bouclefinit
Lire une ligne, la traiter, écraser avec la suivante — tout le fichier ne vit jamais en mémoire. Même un fichier multi-Go n'utilise que « la valeur de la ligne la plus longue » de mémoire. EOF retourne "" pour signaler à la boucle de s'arrêter.
# Style classique : sortir sur chaîne vide
with open("data/log.txt", "r") as f:
    while True:
        line = f.readline()
        if not line:           # chaîne vide = EOF
            break
        print(line.rstrip())

L'opérateur morse := s'écrit en une ligne de moins

Python 3.8 a introduit l'opérateur morse (:=), qui te permet d'affecter et de tester dans une expression. Écrire while line := f.readline(): signifie « mets le résultat de readline() dans line, et continue de boucler tant qu'il est non vide » — toute la boucle en une ligne.

Maintenant lis data/tasks.txt avec readline() + l'opérateur morse, une ligne à la fois. Le cas d'usage réel est les logs gigantesques ; on utilise le petit fichier de tâches juste pour voir la mécanique.

① Ouvre with open("data/tasks.txt", "r") as f:.

② Boucle avec while line := f.readline(): pour que chaque ligne aille dans line.

③ Retire le saut de ligne final avec .rstrip() et imprime : print(line.rstrip()).

Éditeur Python

Exécuter le code pour voir le résultat

Écriture — mode w et mode a

L'écriture est juste open() avec un autre deuxième argument. Deux modes portent le poids pratique.

- "w" (write) — créer ou écraser. Le contenu existant est détruit.

- "a" (append) — ajouter à la fin. Le contenu existant reste.

Deux méthodes d'écriture existent aussi. f.write(s) écrit la chaîne s directement ; f.writelines(lst) écrit une liste de chaînes en un coup. Si le chemin inclut un dossier, le fichier est créé dedans (le dossier doit déjà exister).

w vs a
avant :ABCopen("w")f.write("XYZ")après :XYZavant :ABCopen("a")f.write("XYZ")après :ABCXYZécraseajoute
w efface le contenu existant dès que tu l'ouvres. a ajoute depuis la fin. Choisir le mauvais peut faire sauter un log important — sois délibéré.
# Mode w : écrire des chaînes une à une
with open("data/done.txt", "w") as f:
    f.write("Rédiger le rapport\n")
    f.write("Répondre aux emails\n")

# Mode w : écrire une liste d'un coup avec writelines
with open("data/done.txt", "w") as f:
    f.writelines(["Rédiger le rapport\n", "Répondre aux emails\n", "Assister à la réunion\n"])

# Mode a : ajouter à la fin
with open("data/done.txt", "a") as f:
    f.write("Faire les courses\n")

Les sauts de ligne \n ne sont pas ajoutés automatiquement

Contrairement à print(), ni f.write() ni f.writelines() n'ajoute des sauts de ligne pour toi. Appeler f.write("Hello") deux fois donne HelloHello dans le fichier. Insère des \n explicites partout où tu veux vraiment une rupture de ligne.

Crée un nouveau done.txt (un enregistrement des tâches terminées) dans le dossier data/, écris dedans, et relis-le. Le dossier data/ existe déjà, donc utilise-le directement dans le chemin.

① Ouvre avec with open("data/done.txt", "w") as f:.

② Après f.write("Tâches terminées :\n"), écris f.write("Rédiger le rapport\n") puis f.write("Répondre aux emails\n") — trois écritures au total.

③ Ouvre à nouveau avec un with open("data/done.txt", "r") as f: séparé et print(f.read()) pour afficher tout le contenu.

④ Après l'exécution, clique sur le bouton 📂 Files de l'en-tête — tu verras data/done.txt listé dans le panneau.

Éditeur Python

Exécuter le code pour voir le résultat

Reproduis l'état de data/done.txt du dernier exercice, puis ajoute un nouvel élément à la fin. Vis la différence entre w et a dans un seul script.

① Commence avec with open("data/done.txt", "w") as f: et f.write("Tâches terminées :\nRédiger le rapport\n") pour fixer le contenu initial (ça réinitialise le fichier à chaque exécution).

② Ensuite avec with open("data/done.txt", "a") as f:, ajoute f.write("Répondre aux emails\n").

③ Enfin, ouvre avec "r" et print(f.read()) pour vérifier.

Éditeur Python

Exécuter le code pour voir le résultat

Aller plus loin — Analyser un fichier et sauvegarder le résultat dans un autre

Un des patterns les plus courants en travail réel est lire un fichier d'entrée, faire une analyse, et écrire le résultat dans un fichier séparé. Utilise simplement open() deux fois — une avec "r", une avec "w". Le style le plus propre est de mettre entrée → traitement → sortie dans trois blocs with séparés.

# Analyser data/log.txt et sauvegarder le résultat dans data/log_summary.txt

# (1) Entrée : lire le log dans une liste de lignes
with open("data/log.txt", "r") as src:
    lines = src.readlines()

# (2) Traitement : compter les lignes, capturer la première/dernière entrée
total   = len(lines)
first   = lines[0].rstrip()
last    = lines[-1].rstrip()
summary = f"count: {total}\nfirst: {first}\nlast: {last}\n"

# (3) Sortie : écrire dans un autre fichier
with open("data/log_summary.txt", "w") as dst:
    dst.write(summary)

print("Saved analysis to data/log_summary.txt")

data/products.txt contient 4 lignes au format « nom,prix ». Lis-le, calcule le total, et écris le résultat dans un fichier séparé data/total.txt.

① Ouvre avec with open("data/products.txt", "r") as f: et récupère la liste avec f.readlines().

② Pour chaque ligne, retire le saut de ligne final avec .rstrip() et split sur "," pour obtenir nom et prix. Le prix est une chaîne, donc convertis avec int() avant d'ajouter.

③ Ouvre with open("data/total.txt", "w") as f: et écris le résultat avec f.write(f"total: {total}\n").

④ Vérifie en ouvrant avec "r" et print(f.read()).

Éditeur Python

Exécuter le code pour voir le résultat

encoding="utf-8" est le standard pour l'encodage texte

Sur le vrai Python, tu écris typiquement open(path, "r", encoding="utf-8") pour spécifier l'encodage explicitement. Tenter de lire un fichier Shift-JIS comme UTF-8 lève UnicodeDecodeError, et l'inverse mojibake silencieusement. Le standard mondial est UTF-8 — écris les nouveaux fichiers en UTF-8 par défaut. L'environnement navigateur fixe UTF-8 en interne donc omettre encoding= marche ici, mais fais-en une habitude quand tu écris des scripts locaux.

QUIZ

Vérification des connaissances

Répondez à chaque question une par une.

Question 1Que signifie le deuxième argument "r" dans with open("data/notes.txt", "r") as f: ?

Question 2Quand tu appelles f.readline() à répétition et que le fichier finit, quelle valeur revient ?

Question 3Si data/done.txt a déjà du contenu et que tu l'ouvres avec with open("data/done.txt", "w") as f:, qu'arrive-t-il au contenu existant ?