Fichiers, exceptions et modules
Cours · Python (école d'ingénieur), chapitre 7 · école d'ingénieur, informatique · le début du chapitre, la suite sur Adloun
7.1 Introduction et Motivation
Pour interagir avec le monde extérieur, un programme doit lire et écrire des fichiers (sauvegardes, données physiques, journaux de log). Cependant, les opérations d'entrées/sorties sont sujettes à des erreurs imprévisibles (fichier manquant, permission refusée, disque plein). Il est donc indispensable d'adopter des structures robustes pour gérer l'ouverture des ressources (gestionnaires de contexte) et la capture des anomalies (exceptions). De plus, la modularité du code passe par la création et l'importation de modules, permettant de structurer proprement des projets de grande envergure. Enfin, ce chapitre aborde les aspects pratiques de l'encodage des caractères (ASCII, Latin-1, Unicode/UTF-8), du traitement de fichiers de données structurées (CSV) et d'images numériques.
7.2 Interaction avec le Système d'Exploitation
Le module standard os permet à Python de dialoguer directement avec le système d'exploitation pour manipuler des répertoires et des fichiers.
7.2.1 Le module os
Les fonctions principales pour gérer le système de fichiers sont :
os.getcwd(): renvoie le chemin absolu du répertoire courant (working directory).os.chdir(chemin): change le répertoire courant vers le chemin spécifié.os.listdir(chemin): renvoie la liste des noms des fichiers et dossiers contenus dans le répertoire désigné.os.walk(chemin): parcourt récursivement une arborescence (générateur de tuples (racine, dossiers, fichiers)).
import os
# Affichage du répertoire courant
print("Répertoire actuel :", os.getcwd())
# Liste des fichiers du dossier courant
print("Contenu :", os.listdir("."))
# Parcours récursif d'une arborescence
for racine, dossiers, fichiers in os.walk("."):
for fichier in fichiers:
if fichier.endswith(".py"):
print(f"Fichier Python trouvé : {os.path.join(racine, fichier)}")
7.2.2 Le module pathlib (approche moderne)
Depuis Python 3.4, le module pathlib propose une approche orientée objet pour manipuler les chemins de fichiers, plus lisible et plus robuste que os.path.
from pathlib import Path
# Création d'un chemin
chemin = Path("dossier") / "sous_dossier" / "fichier.txt"
# Vérification d'existence
if chemin.exists():
print("Le fichier existe")
# Lecture simplifiée
contenu = chemin.read_text(encoding="utf-8")
# Écriture simplifiée
chemin.write_text("Nouveau contenu", encoding="utf-8")
# Parcours d'un dossier
for p in Path(".").glob("*.py"):
print(f"Fichier Python : {p.name}")
7.3 Lecture et Écriture de Fichiers
7.3.1 Modes d'Ouverture et Gestionnaires de Contexte
La fonction native open() permet de créer un flux entre le programme et un fichier physique sur le disque. Elle prend deux arguments principaux : le chemin du fichier et le mode d'ouverture.
| Mode | Description |
|---|---|
'r' | Lecture seule (défaut). Le fichier doit exister. |
'w' | Écriture (écrase le fichier s'il existe, le crée sinon). |
'a' | Ajout (append) à la fin du fichier. |
'x' | Création exclusive (erreur si le fichier existe déjà). |
'rb' | Lecture binaire (images, fichiers non textuels). |
'wb' | Écriture binaire. |
Pour garantir la fermeture automatique d'un fichier même si une erreur survient, on utilise le mot-clé with. Le fichier est proprement refermé dès la sortie du bloc indenté.
7.3.2 Méthodes de Lecture
f.read(): lit l'intégralité du fichier en une seule chaîne.f.read(n): lit au maximum caractères.f.readline(): lit la ligne suivante (jusqu'auninclus).f.readlines(): renvoie une liste de toutes les lignes.
with open("exemple.txt", "r", encoding="utf-8") as f:
for num, ligne in enumerate(f, start=1):
print(f"Ligne {num} : {ligne.rstrip()}") # rstrip() enlève le \n final
7.3.3 Méthodes d'Écriture
f.write(chaine): écrit une chaîne dans le fichier (ne rajoute pas automatiquement den).f.writelines(liste): écrit une liste de chaînes (sansnautomatique).
# Écriture avec écrasement
with open("sortie.txt", "w", encoding="utf-8") as f:
f.write("Première ligne\n")
f.write("Deuxième ligne\n")
# Ajout à la fin du fichier
with open("sortie.txt", "a", encoding="utf-8") as f:
f.write("Troisième ligne (ajoutée)\n")
7.4 Fichiers CSV (Comma-Separated Values)
Le format CSV est couramment utilisé pour stocker des tableaux de données. Chaque ligne représente une ligne de tableau, et les colonnes sont délimitées par un caractère (virgule, point-virgule, tabulation).
7.4.1 Lecture naïve avec split()
Supposons un fichier planetes.csv contenant :
Mercure,2439,3.7,88
Vénus,6052,8.9,225
Terre,6378,9.8,365
Mars,3396,3.7,687
Le script suivant lit ce fichier, sépare les colonnes avec la méthode split() et convertit les types :
tab = []
with open("planetes.csv", "r", encoding="utf-8") as f:
for ligne in f:
colonnes = ligne.strip().split(",")
nom = colonnes[0]
rayon = int(colonnes[1])
gravite = float(colonnes[2])
periode = int(colonnes[3])
tab.append([nom, rayon, gravite, periode])
print(tab)
7.4.2 Le module csv (gestion robuste)
Le module standard csv gère correctement les cas complexes (virgules dans les champs, guillemets, etc.).
import csv
# Lecture
with open("planetes.csv", "r", encoding="utf-8") as f:
reader = csv.reader(f, delimiter=',')
for ligne in reader:
print(ligne) # ligne est une liste de chaînes
# Écriture
with open("sortie.csv", "w", encoding="utf-8", newline='') as f:
writer = csv.writer(f, delimiter=';')
writer.writerow(["Nom", "Rayon", "Gravité", "Période"])
writer.writerow(["Terre", 6378, 9.8, 365])
7.5 Encodage des Caractères
7.5.1 Le jeu de caractères ASCII
À l'origine, le codage ASCII représentait les caractères sur 7 bits (128 caractères possibles). Il comprend les lettres capitales et minuscules anglaises, les chiffres, la ponctuation et des caractères de contrôle. En Python, ord() renvoie le code numérique d'un caractère et chr() renvoie le caractère correspondant :
>>> ord('A')
65
>>> chr(97)
'a'
7.5.2 De Latin-1 à Unicode / UTF-8
La norme ISO-8859-1 (Latin-1) utilise le 8e bit pour ajouter 128 caractères (accents européens). Cependant, Latin-1 est limité aux alphabets européens.
Unicode attribue un identifiant numérique unique à chaque caractère de toutes les langues du monde. L'encodage UTF-8 (défaut en Python) stocke ces identifiants sur 1 à 4 octets, tout en conservant une parfaite compatibilité avec l'ASCII (les caractères ASCII sont codés sur un seul octet, identique à leur codage historique).
Si un fichier UTF-8 est ouvert avec un mauvais encodage, des caractères étranges apparaissent ou une exception est levée.
# Bonne pratique : spécifier explicitement l'encodage
with open("fichier.txt", "r", encoding="utf-8") as f:
contenu = f.read()
# Gestion des erreurs d'encodage
with open("fichier.txt", "r", encoding="utf-8", errors="ignore") as f:
contenu = f.read() # ignore les caractères non décodables
7.6 Gestion des Exceptions
Les exceptions sont des signaux émis par Python pour indiquer la survenue d'une erreur (division par zéro, fichier introuvable, type incorrect).
7.6.1 Hiérarchie des Exceptions
7.6.2 Bloc try-except-else-finally
try:
# Code susceptible de lever une exception
valeur = int(input("Entrez un nombre : "))
except ValueError:
# Exécuté si une ValueError est levée
print("Ce n'est pas un nombre valide.")
except ZeroDivisionError:
# Exécuté si une ZeroDivisionError est levée
print("Division par zéro.")
else:
# Exécuté si aucune exception n'a été levée
print(f"Valeur saisie : {valeur}")
finally:
# Toujours exécuté (quoi qu'il arrive)
print("Fin du traitement.")
7.6.3 Lever des exceptions avec raise
def racine_carree(x):
if x < 0:
raise ValueError("La racine carrée n'est pas définie pour les négatifs")
return x ** 0.5
try:
print(racine_carree(-1))
except ValueError as e:
print(f"Erreur : {e}")
7.7 Modules et Packages
7.7.1 Import de modules
Python dispose d'une riche bibliothèque standard. On peut également créer ses propres modules.
# Import simple
import math
print(math.sqrt(2))
# Import avec alias
import numpy as np
# Import sélectif
from os import getcwd, listdir
print(getcwd())
# Import de tout (déconseillé)
from math import *
7.7.2 Création d'un module
Un module Python est simplement un fichier .py. Par exemple, le fichier mon_module.py :
# mon_module.py
def dire_bonjour(nom):
return f"Bonjour, {nom} !"
PI = 3.14159
if __name__ == "__main__":
# Code exécuté uniquement si le fichier est lancé directement
print("Test du module :", dire_bonjour("Monde"))
Utilisation dans un autre script :
import mon_module
print(mon_module.dire_bonjour("Alice"))
print(mon_module.PI)
7.7.3 La condition if __name__ == "__main__"
Cette construction permet de distinguer l'exécution directe d'un script de son import en tant que module. Elle est essentielle pour :
- Tester un module lors de son développement.
- Fournir une interface en ligne de commande à un module réutilisable.
7.7.4 Organisation en packages
Un package est un dossier contenant un fichier __init__.py (qui peut être vide) et des modules.
mon_package/
|-- __init__.py
|-- module1.py
+-- module2.py
Import depuis un package :
from mon_package import module1
from mon_package.module2 import ma_fonction
7.8 Traitement Numérique d'Images (Approfondissement)
Note : Cette section est optionnelle et suppose l'installation de NumPy et Matplotlib.
7.8.1 Modélisation matricielle
Une image numérique est modélisée par une grille bidimensionnelle de pixels.
- Image en niveaux de gris : matrice de dimensions d'entiers entre 0 (noir) et 255 (blanc).
- Image en couleur (RGB) : matrice de dimensions où la troisième dimension représente les canaux Rouge, Vert, Bleu.
La suite du cours est sur Adloun
Le chapitre en entier, formules et figures comprises, avec le tuteur, les fiches, les QCM et les exercices.
Lire la suite du coursEn accès libre, sans inscription.