try en Python : exécuter du code qui peut échouer

Le bloc try isole une opération qui peut échouer, pour que l'erreur soit rattrapée par except au lieu de tout arrêter.
5 min de lecture
Believemy logo

Définition

Une erreur qui n'est pas prévue arrête un programme Python net, à l'endroit où elle survient. Une saisie qui n'est pas un nombre, un fichier absent, une connexion perdue : le résultat est toujours le même, l'exécution s'interrompt et tout le travail déjà accompli part avec elle. try existe pour éviter ce sort aux erreurs qu'on sait pouvoir se produire.

Le principe se comprend vite. try ouvre un bloc de code susceptible de lever une exception. Tant que rien ne va mal, le programme avance comme si ce bloc n'existait pas. Dès qu'une erreur survient à l'intérieur, l'exécution abandonne aussitôt le reste du try et saute directement au bloc except capable de la traiter.

PYTHON
try:
    age = int(saisie)
except ValueError:
    print("Ce n'est pas un nombre")
    age = None

Avec ces quelques lignes, une saisie farfelue ne fait plus planter le programme : elle déclenche un message clair, et l'exécution continue avec age à None plutôt que de s'arrêter. C'est ce qui sépare un programme qui casse à la première anicroche d'un programme qui encaisse.


Garder le bloc le plus court possible

Une fois qu'on connaît try, la tentation naturelle est d'en mettre le plus possible à l'intérieur, pour ne rien oublier. C'est pourtant l'erreur la plus fréquente. Un bloc qui enferme trente lignes derrière un seul except Exception attrape n'importe quel échec survenu parmi ces trente lignes, sans jamais préciser lequel.

Le coût se voit en production, le jour où le message affiché est un simple « Erreur », alors que la vraie cause peut être un fichier manquant, un calcul qui divise par zéro, ou une variable mal orthographiée. Ces trois problèmes reçoivent la même réponse muette, et corriger le bug oblige à tout relire pour deviner ce qui a réellement cassé.

PYTHON
# Trop large : on ne sait plus ce qui a échoué
try:
    donnees = charger(fichier)
    resultat = calculer(donnees)
    enregistrer(resultat)
except Exception:
    print("Erreur")

# Ciblé : on sait, et on peut réagir
try:
    donnees = charger(fichier)
except FileNotFoundError:
    donnees = valeurs_par_defaut()

Dans la pratique, cela donne une seule règle : une opération risquée par bloc, rattrapée par une exception nommée précisément. C'est ce qui permet, dans la version ciblée, de savoir que seul le chargement peut échouer, et de proposer une valeur par défaut sans deviner si le problème venait du calcul ou de l'enregistrement.

Attention

Un except: écrit sans aucun nom d'exception va plus loin encore : il attrape aussi les interruptions volontaires, comme un Ctrl+C ou un appel à sys.exit(). Le programme refuse alors de s'arrêter quand on le lui demande, ce qui ressemble à un blocage.


Les quatre blocs

try ne travaille jamais seul. Trois autres blocs peuvent l'accompagner, chacun réservé à un moment précis de l'exécution. Le tableau suivant les résume, avant que les deux plus utiles soient détaillés juste après.

BlocQuand il s'exécute
tryToujours, jusqu'à la première erreur
exceptSeulement si l'exception correspond
elseSeulement si aucune exception n'est survenue
finallyDans tous les cas, erreur ou non

Le bloc else est le moins connu des quatre, et pourtant il résout un vrai problème : où mettre la suite du traitement, celle qui ne doit avoir lieu que si tout s'est bien passé ? La réponse est de la mettre dans else, ce qui garde le try réduit à la seule ligne réellement risquée.

Rien n'empêche non plus d'enchaîner plusieurs except après un seul try, chacun ciblant une exception différente. Python les lit dans l'ordre où ils sont écrits et s'arrête au premier qui correspond, un détail qui a des conséquences concrètes sur la façon de les ranger, développées dans la section suivante.


Plusieurs rattrapages, du précis au général

Un appel à une API, par exemple, peut échouer de plusieurs façons bien distinctes, et chacune appelle une réponse différente. Un délai dépassé ne se traite pas comme une coupure réseau, elle-même différente d'une réponse reçue mais illisible. Enchaîner plusieurs blocs except après un seul try permet de répondre à chaque cas séparément plutôt que de les confondre dans un seul rattrapage vague.

PYTHON
try:
    reponse = appeler_api(url)
except TimeoutError:
    reponse = cache.lire(url)          # le service est lent
except ConnectionError:
    reponse = None                     # le réseau est coupé
except ValueError as erreur:
    journaliser(f"Réponse illisible : {erreur}")
    reponse = None

Python lit ces blocs de haut en bas et s'arrête au premier qui correspond à l'exception réellement levée. Cela veut dire que l'ordre n'est pas affaire de goût : un cas large placé en premier absorberait silencieusement tous les cas plus précis placés après lui, et le code écrit pour TimeoutError ne s'exécuterait jamais, sans le moindre avertissement.

Quand deux exceptions différentes appellent exactement le même traitement, inutile de dupliquer le bloc : elles se regroupent avec un tuple, par exemple except (TimeoutError, ConnectionError):. Cette écriture évite de répéter deux fois la même réponse pour deux causes similaires.


Questions fréquentes

Question

Peut-on utiliser try dans une boucle ?

Oui, et c'est même l'usage le plus courant dans un traitement par lots. Une ligne fautive est écartée et journalisée, pendant que la boucle continue sur les suivantes sans tout interrompre. Un bloc try qui ne lève finalement rien ne coûte pratiquement aucun temps d'exécution.

Question

Comment connaître le détail de l'erreur attrapée ?

En écrivant except ValueError as erreur:, ce qui met l'objet exception à disposition sous ce nom à l'intérieur du bloc. L'afficher ou le journaliser donne le message exact fourni par Python, bien plus utile pour déboguer qu'un simple « une erreur est survenue » qui n'aide personne.

Question

Faut-il tout vérifier avant plutôt que d'utiliser try ?

Python recommande l'inverse : tenter l'opération, puis rattraper l'échec si besoin. Vérifier qu'un fichier existe avant de l'ouvrir laisse une fenêtre de temps pendant laquelle il peut disparaître entre la vérification et l'ouverture, alors que try couvre l'opération elle-même, sans laisser cette faille ouverte.

Termes connexes

Découvrez notre glossaire Python

Parcourez les termes et définitions les plus couramment utilisés dans le domaine du développement avec Python.

Partager cet article

Tu veux nous aider ? Fais un lien vers cet article sur tes réseaux ou encore mieux : sur ton site, dans un article ou dans ta newsletter.