Apprenez en lisant dans l'ordre

shutil et tempfile — Opérations en masse et fichiers temporaires

Apprends shutil et tempfile de Python depuis la base. Opérations en masse sur les fichiers avec shutil.copy / shutil.move / shutil.rmtree, plus comment utiliser les fichiers temporaires en sécurité via tempfile.NamedTemporaryFile — le tout en pratique.

Cet article parcourt deux modules : shutil, qui opère sur des fichiers et des dossiers entiers, et tempfile, qui gère des fichiers temporaires jetables. Tu couvriras les opérations en masse sur les fichiers avec shutil.copy / move / rmtree, la façon sûre d'utiliser NamedTemporaryFile, et le motif d'écriture atomique qui combine les deux.

shutil — Opérations sur fichiers et dossiers en une ligne

shutil veut dire shell utilities — c'est la bibliothèque standard qui te laisse appeler des opérations style shell comme cp / mv / rm -r depuis Python en une seule ligne. Le module os a des choses comme os.rename, mais shutil ajoute des opérations de plus haut niveau comme la copie récursive de dossier et la suppression d'arborescence.

Trois fonctions principales de shutil
shutil.copy(src, dst)Faire une copieshutil.move(src, dst)Déplacer ou renommershutil.rmtree(path)Suppression récursive
copy duplique un fichier vers un autre emplacement, move le déplace (ou le renomme sur place), et rmtree supprime récursivement un dossier entier. Ces trois couvrent la plupart des opérations quotidiennes.
FonctionComportementNotes
shutil.copy(src, dst)Dupliquer un fichierSi dst est un dossier, ça va dedans avec le même nom
shutil.copy2(src, dst)copy plus métadonnées comme la date de modificationBon pour les sauvegardes
shutil.copytree(src, dst)Dupliquer récursivement un dossier entierdst **ne doit pas exister**
shutil.move(src, dst)Déplacer ou renommer un fichier ou dossierÉquivalent à rename quand src et dst partagent le même parent
shutil.rmtree(path)Supprimer récursivement un dossier et son contenuPas réversible — vérifie deux fois la cible avant d'exécuter
import shutil
import os

# 1) Copier un fichier vers un autre emplacement (une sauvegarde typique)
os.makedirs("backups", exist_ok=True)        # S'assurer que le dossier de destination existe
shutil.copy("data/sales.csv", "backups/sales_2024.csv")

shutil.move("logs/temp.log", "logs/archive_2024.log")

shutil.rmtree("old_data")

rmtree ne peut pas être annulé

shutil.rmtree(path) supprime physiquement tout sous path. Python ne passe pas par une corbeille — c'est parti instantanément. Dans un vrai projet, affiche la cible avant de supprimer, ajoute une garde comme if path.startswith("/tmp"), et construis des habitudes qui te protègent toi et ton code.

Sauvegarde le CSV de ventes data/sales.csv sous backups/sales_backup.csv. Tu peux inspecter l'original depuis le panneau 📂 Files à gauche.

① Importe shutil et os.

② Prépare le dossier de destination backups/ (d'une façon qui n'erre pas s'il existe déjà).

③ Copie le fichier vers le nom de destination ci-dessus.

④ Vérifie à la fois la sauvegarde et l'original en affichant Backup done: True / Source still exists: True.

(Si tu l'exécutes correctement l'explication apparaît en dessous.)

Éditeur Python

Exécuter le code pour voir le résultat

tempfile — Créer en sécurité des fichiers jetables

tempfile est la bibliothèque standard pour les fichiers temporaires qui sont automatiquement nettoyés quand tu en as fini avec eux. Tu l'utilises pour stocker des résultats intermédiaires, mettre en tampon des données volumineuses, garder des dossiers de travail de test — tout ce qui n'a besoin d'exister que pendant que le processus tourne.

Si tu fabriques tes propres noms de fichiers comme tmp_xxx.txt, tu risques de rentrer en collision avec d'autres processus ou d'oublier de les supprimer. tempfile crée à la place des fichiers dans le dossier temp de l'OS sous un nom garanti unique, et les supprime automatiquement quand le travail est fini.

Cycle de vie de NamedTemporaryFile
with NamedTemporaryFile():→ Fichier temp crééDans le bloc :écrire et lireSortie du bloc→ Auto-suppressionUtilise-le en sécuritésans nettoyage
Le fichier est créé à l'instant où tu entres dans le bloc with, et est supprimé automatiquement quand tu en sors. Le nom de fichier est attribué sur place pour éviter les collisions — tu ne le choisis pas toi-même.
Fonction / attributSignificationNotes
tempfile.NamedTemporaryFileFichier temp que tu ouvres et fermes avec `with`delete=False le garde après le bloc
tempfile.mkdtemp()Retourne le chemin d'un dossier tempTu le supprimes toi-même avec shutil.rmtree
tempfile.gettempdir()Retourne le chemin du dossier temp de l'OS/tmp sur Linux, chemin différent sur macOS
tf.nameLe chemin de fichier réel (nom aléatoire)Accessible dans le bloc `with`
tf.write / tf.readMême API qu'un objet fichier ordinaireChoisis 'w' / 'r' / 'w+' via l'argument mode
import tempfile
import os

# Ouvrir en sécurité avec `with`, puis auto-suppression
with tempfile.NamedTemporaryFile(mode="w+", suffix=".txt", delete=True) as tf:
    tf.write("données d'agrégation intermédiaires\n")
    tf.seek(0)
    print("Content:", tf.read())
    print("Path:", tf.name)
# ← Le bloc se termine ici et le fichier est auto-supprimé

Quand combiner delete=False avec `with`

Quand tu veux écrire le fichier et le relire plus tard depuis ailleurs, passe delete=False pour que le fichier survive à la sortie du bloc with. Une fois que tu en as fini avec lui, soit tu l'enlèves toi-même avec os.remove(path), soit tu le bascules dans la vraie destination avec shutil.move — c'est le motif d'écriture atomique couvert ci-dessous.

Crée un fichier temporaire, écris dedans, puis vérifie s'il existe avant et après suppression. Ouvre un NamedTemporaryFile avec delete=False, écris dedans, relis, vérifie l'existence avant suppression, supprime-le, puis vérifie l'existence à nouveau.

① Importe tempfile et os.

② Ouvre un fichier temp avec NamedTemporaryFile(mode="w", delete=False), écris la chaîne sales total: 3750 dedans, sauvegarde tf.name dans une variable de chemin, et sors du bloc with.

③ Affiche l'existence avec os.path.exists(path) sous la forme Exists before delete: ◯◯.

④ Supprime le fichier avec os.unlink(path).

⑤ Affiche l'existence à nouveau avec os.path.exists(path) sous la forme Exists after delete: ◯◯.

Éditeur Python

Exécuter le code pour voir le résultat

Fichiers temp auto-supprimés avec `delete=True`

Si tu écrases un fichier de configuration ou d'état important directement avec open("settings.json", "w"), un crash de processus en milieu d'écriture peut laisser un fichier à moitié écrit derrière, qui échoue ensuite à l'analyse à la prochaine lecture. La façon standard d'éviter ça est le motif « écrire complètement dans un fichier temp, puis le renommer / le déplacer dans le vrai chemin » — connu sous le nom d'écriture atomique (atomique — même si interrompu, les observateurs ne peuvent voir que « complété » ou « pas commencé », jamais un état entre les deux).

Flux d'une écriture atomique
open direct("w")Crash en milieu d'écritureFichier cassélaissé derrièreÉcrire complètementdans tempfileshutil.move versle vrai cheminLe basculement estinstantané de l'extérieurÉtat casséjamais visible
Écrire directement laisse un fichier cassé derrière en cas de crash, mais passer par un fichier temp bascule vers le vrai chemin uniquement au moment où l'écriture est complète — donc l'état cassé n'est jamais visible.
import tempfile
import shutil
import json

final_path = "settings.json"
new_settings = {"theme": "dark", "lang": "fr", "fontSize": 14}

# 1) Écrire complètement dans un fichier temp
with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".json") as tf:
    json.dump(new_settings, tf)
    temp_path = tf.name

# 2) Une fois fini, déplacer dans le vrai chemin (ce moment unique est le « basculement »)
shutil.move(temp_path, final_path)

# 3) Vérifier
with open(final_path) as f:
    print(json.load(f))
# → {'theme': 'dark', 'lang': 'fr', 'fontSize': 14}

Un objet fichier a une position courante de lecture/écriture (curseur), et appeler `tf.write(...)` déplace le curseur juste après ce qui a été écrit (= la fin). Appeler tf.read() à partir de là retourne une chaîne vide parce qu'il n'y a rien après le curseur, donc le geste standard est de remettre le curseur au début avec `tf.seek(0)` avant de lire.

Comment se comportent le curseur de fichier et seek(0)
write("config: ok")Curseur → finread()→ "" (vide)seek(0)Curseur → débutread()→ "config: ok"
write déplace le curseur à la fin → lire à partir de là retourne une chaîne videseek(0) ramène le curseur au début → read retourne ce que tu as écrit.

mode="w+" est le mode lecture-écriture

`mode="w+"` est le mode qui te laisse à la fois écrire et lire à travers le même handle de fichier. Avec juste "w" tu es en écriture seule et read() ne fonctionne pas ; avec juste "r" tu es en lecture seule et write() ne fonctionne pas. Pour des exercices qui écrivent et relisent immédiatement, "w+" est requis.

Crée un fichier temp avec `with NamedTemporaryFile(delete=True)` et confirme qu'il est auto-supprimé. Écris dedans dans le bloc with, relis, puis vérifie l'existence après que le bloc soit sorti — ça doit être False.

① Importe tempfile et os.

② Ouvre tempfile.NamedTemporaryFile(mode="w+", delete=True) avec un with (mode="w+" est lecture-écriture).

③ Dans le bloc, écris tf.write("config: ok\n"), remets le curseur au début avec tf.seek(0), relis avec tf.read(), et affiche-le sous la forme Content: ◯◯.

④ Sauvegarde le chemin dans le bloc comme saved_path = tf.name.

⑤ Après être sorti du bloc, affiche le résultat de os.path.exists(saved_path) sous la forme Exists after with: ◯◯ (ça doit être False).

Éditeur Python

Exécuter le code pour voir le résultat
QUIZ

Vérification des connaissances

Répondez à chaque question une par une.

Question 1Lequel des suivants utilises-tu quand tu veux supprimer récursivement un dossier entier ?

Question 2Quelle est une raison typique d'utiliser tempfile.NamedTemporaryFile avec delete=False ?

Question 3Quelle est l'essence de l'écriture atomique ?