iducationducation
IndexArticlesFormationsProfilOutilsBibliothech
N°014 — 2026
Navigation
01Index02Articles03Formations04Profil05Outils06Bibliothech
N°014 — 2026
iducationducation
IndexArticlesFormationsProfilOutilsBibliothech
N°014 — 2026
Navigation
01Index02Articles03Formations04Profil05Outils06Bibliothech
N°014 — 2026
Formations
Python · Débutant

Python

Apprendre Python de zéro jusqu'au niveau expert : syntaxe, structures de données, POO, générateurs, décorateurs, typage, tests, async et internals du langage.

Python 3.13uvpytestmypyasyncio
01Introduction et installation02Variables et types de base03Conditions et boucles04Fonctions05Listes, tuples, dictionnaires et ensembles06Modules, fichiers et exceptions07Programmation orientée objet08Itérateurs, générateurs, décorateurs et context managers09Typage statique et tests10Concurrence : threads, processus et asyncio11Niveau expert : internals, métaprogrammation et performance
Chapitre 6·40 min

Modules, fichiers et exceptions

Un script d'une page devient vite un projet de vingt fichiers. Ce chapitre couvre trois compétences qui marquent le passage du débutant à l'intermédiaire : découper son code en modules, lire et écrire des fichiers proprement, et gérer les erreurs au lieu de les subir.

Modules et imports

Tout fichier .py est un module. Un dossier contenant des modules est un package.

app/
├── pyproject.toml
└── src/
    └── boutique/
        ├── __init__.py
        ├── panier.py
        └── paiement/
            ├── __init__.py
            └── stripe.py
import math
from pathlib import Path
from boutique.panier import Panier
from boutique.paiement import stripe as pay
import numpy as np   # alias conventionnel

Évitez from module import * : on ne sait plus d'où vient un nom.

Le garde __main__

Un module est exécuté à son import. Pour qu'un fichier soit à la fois importable et exécutable :

outils.py
def slugifier(texte: str) -> str:
    return "-".join(texte.lower().split())
 
if __name__ == "__main__":
    print(slugifier("Mon Super Titre"))

__name__ vaut "__main__" quand le fichier est lancé directement, et "outils" quand il est importé.

La bibliothèque standard

Python est livré « piles incluses ». Avant d'installer un paquet, vérifiez ce qui existe déjà :

ModuleUsage
pathlibchemins de fichiers
json, csv, tomllibformats de données
datetime, zoneinfodates et fuseaux
reexpressions régulières
subprocesslancer des commandes
argparseparser les arguments CLI
loggingjournalisation
itertools, functoolsoutils fonctionnels
sqlite3base SQL embarquée

Fichiers avec pathlib

pathlib remplace os.path avec une API objet.

from pathlib import Path
 
racine = Path("data")
racine.mkdir(exist_ok=True)
 
fichier = racine / "notes.txt"          # l'opérateur / joint les chemins
fichier.write_text("Bonjour\n", encoding="utf-8")
contenu = fichier.read_text(encoding="utf-8")
 
fichier.exists()      # True
fichier.suffix        # '.txt'
fichier.stem          # 'notes'
 
for csv in racine.glob("**/*.csv"):
    print(csv)

Précisez toujours encoding="utf-8". Sur Windows, l'encodage par défaut a longtemps été cp1252, source de caractères corrompus.

Le bloc with

Pour les gros fichiers, on lit ligne par ligne avec open() dans un bloc with. Le fichier est fermé automatiquement, même en cas d'erreur.

with open("access.log", encoding="utf-8") as f:
    for ligne in f:              # lecture paresseuse, pas tout en mémoire
        if "500" in ligne:
            print(ligne.rstrip())

Modes : "r" lecture, "w" écriture (écrase), "a" ajout, "b" binaire ("rb", "wb").

JSON et CSV

import json, csv
 
data = {"nom": "Ada", "langages": ["Python", "C"]}
Path("user.json").write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8")
charge = json.loads(Path("user.json").read_text(encoding="utf-8"))
 
with open("ventes.csv", newline="", encoding="utf-8") as f:
    for row in csv.DictReader(f):
        print(row["produit"], float(row["montant"]))

Exceptions

Une exception interrompt le flux normal. Si personne ne l'attrape, le programme s'arrête avec une traceback.

try:
    age = int(input("Âge : "))
except ValueError:
    print("Ce n'est pas un nombre")
else:
    print(f"Dans 10 ans : {age + 10}")     # si aucune exception
finally:
    print("Toujours exécuté")

Plusieurs types, et accès à l'objet exception :

try:
    resultat = charger_config(chemin)
except FileNotFoundError:
    resultat = CONFIG_PAR_DEFAUT
except (json.JSONDecodeError, KeyError) as e:
    raise SystemExit(f"Config invalide : {e}")

Ne jamais avaler les erreurs

try:
    traiter()
except Exception:
    pass          # le pire code Python qui existe

Ce bloc cache tous les bugs, y compris les fautes de frappe. Attrapez l'exception précise que vous savez gérer, laissez remonter le reste.

Lever ses propres exceptions

class StockInsuffisant(Exception):
    def __init__(self, produit: str, demande: int, dispo: int):
        super().__init__(f"{produit} : {demande} demandés, {dispo} en stock")
        self.produit = produit
 
def retirer(produit, quantite):
    dispo = stock[produit]
    if quantite > dispo:
        raise StockInsuffisant(produit, quantite, dispo)
    stock[produit] -= quantite

Chaîner une exception pour garder la cause d'origine :

try:
    row = db.fetch(user_id)
except ConnectionError as e:
    raise ServiceIndisponible("Base injoignable") from e

EAFP plutôt que LBYL

Python préfère « Easier to Ask Forgiveness than Permission » : tenter l'opération et gérer l'échec, plutôt que tout vérifier avant.

# LBYL — race condition possible entre le test et l'ouverture
if chemin.exists():
    data = chemin.read_text()
 
# EAFP — idiomatique
try:
    data = chemin.read_text()
except FileNotFoundError:
    data = ""

Logging plutôt que print

import logging
 
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s")
log = logging.getLogger(__name__)
 
log.info("Import démarré")
log.warning("Ligne %d ignorée", 42)
try:
    1 / 0
except ZeroDivisionError:
    log.exception("Calcul impossible")   # inclut la traceback

Exercice : un petit outil CLI

compter.py
import argparse
from pathlib import Path
 
parser = argparse.ArgumentParser(description="Compte les lignes des fichiers")
parser.add_argument("dossier", type=Path)
parser.add_argument("--ext", default=".py")
args = parser.parse_args()
 
total = 0
for f in args.dossier.rglob(f"*{args.ext}"):
    try:
        n = sum(1 for _ in f.open(encoding="utf-8"))
    except UnicodeDecodeError:
        continue
    total += n
    print(f"{n:6} {f}")
print(f"{total:6} TOTAL")
python compter.py src --ext .py

Modules pour organiser, pathlib et with pour les fichiers, exceptions précises pour les erreurs : c'est l'hygiène de base d'un code Python qu'on peut maintenir. La suite passe à la programmation orientée objet.

Précédent
Listes, tuples, dictionnaires et ensembles
Suivant
Programmation orientée objet

Développeur fullstack passionné. J'apprends en construisant et je documente tout — front, back, outils. Le code s'apprend mieux en public.

Naviguer

IndexTous les articlesFormationsProfilOutilsBibliothech

Ailleurs

GitHub RSS

Newsletter

Les articles, libs et découvertes. Une fois par semaine, pas plus.

© 2026 William LoreeConçu & codé à la main