Le traceback en Python : lire le rapport d'erreur

Le traceback est le rapport que Python affiche après une exception non rattrapée : il se lit de bas en haut, jamais l'inverse.
5 min de lecture
Believemy logo

Définition

Un programme Python qui plante n'affiche jamais une simple ligne d'erreur, mais un bloc de texte qui peut décourager la première fois qu'on le découvre. Ce bloc n'est pourtant pas du bruit : c'est la seule information complète sur ce qui s'est passé, et savoir la lire fait gagner un temps précieux face à une erreur.

Ce bloc s'appelle le traceback. Il apparaît quand une exception remonte sans être rattrapée, et il retrace le chemin parcouru par l'erreur : quelle ligne l'a déclenchée, quelle fonction appelait celle-là, et ainsi de suite jusqu'au point d'entrée du programme. Voici à quoi il ressemble lorsqu'une commande cherche une clé absente d'un dictionnaire :

PYTHON
Traceback (most recent call last):
  File "app.py", line 42, in <module>
    total = facturer(commande)
  File "facturation.py", line 18, in facturer
    return prix * commande["quantite"]
KeyError: 'quantite'


Il se lit de bas en haut

Le réflexe naturel consiste à lire ce bloc comme un texte ordinaire, du haut vers le bas. C'est précisément ce qu'il ne faut pas faire, et personne ne le dit jamais clairement. Python empile les blocs à mesure que l'erreur remonte d'une fonction vers celle qui l'a appelée : le bloc le plus récent, donc le plus proche de la cause, se retrouve mécaniquement en bas.

La dernière ligne donne le type d'erreur et son message : c'est ce qui s'est passé. Le bloc juste au-dessus donne l'endroit exact, avec le fichier, la ligne et le code fautif : c'est là que ça s'est passé.

Les blocs restants, au-dessus, racontent comment on en est arrivé là : la chaîne des fonctions qui se sont appelées avant que l'erreur ne survienne. Utile pour le contexte, moins pour trouver la cause elle-même.

Le schéma suivant reprend ces trois niveaux sur l'exemple précédent :

Un traceback se lit de bas en hautTrois blocs empilés. En bas, la dernière ligne donne le type et le message de l'erreur : ce qui s'est passé. Juste au-dessus, le fichier et la ligne fautive : où. Au-dessus encore, la chaîne des appels : comment on en est arrivé là. Une flèche remonte du bas vers le haut.Traceback (most recent call last):File "app.py", line 42, in <module>total = facturer(commande)File "facture.py", line 18, in facturerreturn prix * commande["quantite"]KeyError: 'quantite'321commentoùquoion lit de bas en haut : quoi, puis où, puis comment

Ce que chaque niveau apporte se résume dans ce tableau :

Où regarderCe qu'on y trouve
Dernière ligneLe type d'erreur et son message
Bloc juste au-dessusLe fichier, la ligne et le code fautif
Blocs précédentsLa chaîne des appels, du plus récent au plus ancien
Première ligneLe point d'entrée du programme

La mention « most recent call last », sur la toute première ligne du traceback, confirme cette règle de lecture : l'appel le plus récent est bien celui du bas.

Attention

Un piège courant consiste à ouvrir le fichier mentionné tout en haut du traceback, en pensant y trouver la cause. C'est presque toujours le mauvais réflexe : ce bloc est le plus ancien de la pile, souvent le point d'entrée du programme, loin de l'endroit où l'erreur a réellement été déclenchée. Le fichier à ouvrir en premier est celui du bloc juste au-dessus de la dernière ligne.


Trouver son propre code

Sur un projet qui utilise plusieurs bibliothèques, une bonne partie des blocs d'un traceback pointe vers des fichiers qui ne sont pas les vôtres, mais vers des paquets installés dans un environnement virtuel. Les parcourir un par un pour trouver ce qui a réellement cassé fait perdre du temps.

Le réflexe efficace consiste à repérer le dernier bloc qui mentionne un fichier de votre projet. C'est presque toujours là que se trouve la cause, même si l'erreur est techniquement levée trois niveaux plus bas, à l'intérieur d'une bibliothèque.

Bon à savoir

Depuis Python 3.11, la ligne fautive est parfois soulignée par une rangée d'accents circonflexes qui pointent l'expression précise en cause. Un repère utile quand une ligne enchaîne plusieurs appels, comme a().b().c(), et qu'il faut savoir lequel des trois a échoué.

Une exception chaînée ajoute une seconde partie au traceback, séparée par une phrase reconnaissable. « The above exception was the direct cause of » signale un chaînage volontaire, écrit avec raise ... from : l'auteur a choisi de documenter le lien entre les deux erreurs. « During handling of the above exception » signale au contraire un incident survenu dans un bloc except, sans intention de chaînage.


L'obtenir sans planter

Laisser le traceback s'afficher dans le terminal convient en développement, puisque quelqu'un regarde l'écran. Cela change dès que le code tourne sans surveillance, dans une tâche planifiée ou un service en production : personne ne lit cette sortie, et l'information disparaît au moment où elle serait la plus utile.

Le module traceback de la bibliothèque standard résout ce problème en transformant le rapport en simple texte, récupérable avec une fonction comme format_exc(). Ce texte part alors dans un journal consultable plutôt que dans une sortie que personne ne surveille, ce qui garde l'erreur diagnosticable longtemps après qu'elle s'est produite.


Questions fréquentes

Question

Pourquoi mon traceback ne mentionne-t-il pas la vraie cause ?

Le plus souvent parce qu'un bloc except a intercepté l'erreur d'origine puis en a levé une autre sans la relier explicitement. Ajouter from à ce raise rétablit ce lien : la cause initiale réapparaît alors dans le rapport, juste au-dessus de la nouvelle erreur.

Question

Que signifie « in <module> » ?

Que la ligne se trouve au niveau du fichier lui-même, en dehors de toute fonction. C'est le corps du script, celui qui s'exécute directement au lancement, sans qu'aucune fonction n'ait été appelée pour y arriver.

Question

Comment garder la trace tout en continuant l'exécution ?

En journalisant l'exception à l'intérieur du bloc except, avec un module de journalisation qui enregistre la trace complète plutôt qu'un simple message. Le programme poursuit son exécution, et l'information reste disponible pour un diagnostic ultérieur.

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.