L'investisseur technique des startups

Tous les articles > Technique > Mise en forme de tracebacks python

Mise en forme de tracebacks python

(sans saigner des yeux)

Chercher des informations dans des logs informes ou dans des tracebacks est à bien des égards une activité frustrante. À Yaal nous utilisons donc sentry, qui est capable d'agréger, de contextualiser et de mettre en forme les logs et les tracebacks que nous générons. Couplé à un système d'alertes efficace, l'outil s'avère très utile pour savoir ce qui se passe en production, et diagnostiquer rapidement lorsque surgissent des problèmes.

Dans la phase itérative du développement d'une fonctionalité, on génère souvent beaucoup d'erreurs temporaires et sans grande valeur. Les capacités qu'a Sentry à contextualiser et mettre en forme une erreur sont intéressante, mais on se passerait bien de l'historique et des alertes dans ce cas de figure. En plus de ça, ça fait un outil (de plus) à ouvrir, une page à actualiser... Bref, lorsque l'on développe et qu'un bug se produit, on veut avoir une information riche et lisible rapidement.

D'aucuns argueront que pour débugger, on utilise un debugger. Certes, mais l'utilisation d'un debugger est assez lourde, et de fait elle n'est pas automatique. De plus, on peut chercher à obtenir une information claire et instantanée sur des exceptions dans des contextes où un debugger n'est pas forcément pertinent. Je pense notamment dans des cas où l'on exécute en même temps plusieurs programmes qui interagissent entre eux (des démons, des serveurs web...), on ne lance pas un débugger derrière chaque programme dans ces cas-là avant (du moins, pas avant d'avoir rencontré un bug).

Comparons quelques outils de mise en forme de backtrace python, en gardant quelques critères en tête :

  • La capacité de mettre une traceback en couleur ;
  • La capacité de contextualiser les appels (afficher les quelques lignes de code avant ou après) ;
  • La capacité d'afficher les variables locales à chaque étape de la stack ;
  • Les methodes d'utilisation et l'invasivité (hook qui s'installe et attrape toutes les exceptions, utilisation manuelle dans des try-except, utilisation comme module python ex:python -m foobar monscript.py) ;
  • L'intégration dans une stack web (middleware WSGI) ;
  • Le packaging avec pip et les dépendances ;
  • L'activité et la taille du projet.

Une traceback par défaut Un exemple de traceback dans sentry

Nous ne nous intéresseront pas à l'affichage des tracebacks dans les programmes de test unitaires.

Outils orienté terminal

Prenons un exemple de code en python s'exécutant dans un terminal.

Une traceback par défaut Un script simple

L'affichage par défaut des tracebacks python donne le minimum d'information, mais on pourrait sans doute faire mieux. Où est la mise en forme ? Quelles sont les variables locales à chaque étape de la pile ?

backtrace

backtrace est un petit projet (30 commits) disponible dans pip. Il s'utilise seulement en hook, s'axe sur une mise en forme succincte et colorée, avec quelques options de personnalisation. Les variables locales ne peuvent pas être affichées mais la fonctionnalité est envisagée.

Un script simple avec backtrace backtrace comme hook

colored-traceback

colored-traceback est un petit projet (9 commits) disponible dans pip. Il se présente comme un module python ou un hook, et se contente de rajouter de la couleur aux tracebacks générées par python, en gardant la même mise en forme. Il y a un petit problème dans l'utilisation par le module python : colored-traceback apparaît lui-même dans la traceback, ce qui n'est facilite pas sa lisibilité.

colored-traceback utilisé comme module colored-traceback utilisé comme module

colored-traceback utilisé comme hook colored-traceback comme hook

pygments

pygments est un outil de coloration syntaxique en python actif, disponible sur pip. pygments est capable de colorer des tracebacks python mais se cantonne à son rôle de coloration syntaxique, donc aucune mise en forme ou contexte ne sont ajoutés. Aucune aide n'est disponible non plus pour attraper les exceptions de manière automatique dans le code. On peut s'en sortir en écrivant un hook, ou une fonction de traitement dans un block try-except. Le binaire pygmentize fourni dans le paquet permet tout de coloriser la sortie standard d'un script python.

hook fait main avec pygments hook fait-main avec pygments

sortie standard capturée avec pygmentize sortie standard capturée avec pygmentize

IPython ultratb

IPython est shell python assez puissant (avec coloration, autocomplétion et autres) disponible dans pip. Par défaut il met en forme les tracebacks avec son module ultratb. Ultratb peut s'utiliser soit comme un hook qui attrape et traîte les exception d'un script, ou dans un bloc try-except. Ultratb est surtout utilisé par défaut dans IPython, donc utiliser ipython comme interpréteur à la place de python peut suffir à afficher une traceback mise en forme. Plusieurs thèmes de couleur, et plusieurs mises en formes sont disponibles. Parmi les mises en forme proposés, on peut afficher une traceback simple, colorée avec ColorTB, ou une traceback avec du contexte, de la couleur, et le contenu des variables locales avec VerboseTB. Il semblerait qu'on ne puisse pas installer ultratb sans installer IPython.

Un script simple avec ipython Un script simple avec IPython

ultratab comme hook ultratab comme hook

ultratab dans un try-except ultratab dans un try-except

ultratab en mode verbeux ultratab en mode verbeux

Outils orienté web

cgitb

cgitb est un mystère. C'est un module cœur de python, originellement utilisé pour générer des pages HTML mettant en forme des tracebacks, mais il peut aussi être utilisé pour du texte. Le module existe depuis Python 2.2 mais il a l'air assez peu connu du web, les deux paragraphes de documentation n'inspirent pas confiance, (deux nouveaux paragraphes ont été écrits pour python 3.8 \o/). Il existe un hook, mais il ne fait qu'écrire sur la sortie standard, sans doute est-ce un reliquat de l'époque où on l'utilisait dans des CGI. Néanmoins, en utilisant les fonctions non documentées du module, on peut arriver à générer des backtraces plutôt riches et avec du contexte. Par contre, pour des couleurs ou des pages web lisibles, on repassera. Les pages web générées sont aussi hideuses que leur code, et la sortie texte est monochrome. Les hooks, l'affichage dans un try-except sont possibles, mais en l'écrivant à la main.

try-except avec cgitb try-except avec cgitb

magnifique page web avec cgitb Une magnifique page web générée par cgitb

django

Le célèbre framework web django permet de mettre en forme les tracebacks python qui peuvent survenir lors de la génération d'une page web. Le module est dans le cœur de django, et n'est pas facilement réutilisable hors django. Il ne génère une traceback monochrome mise en forme, avec du contexte et des variables locales.

traceback web avec django Traceback web avec django

werkzeug

Werkzeug embarque un middleware WSGI qui produit des pages HTML riches et belles, avec des accordéons pour ne pas la charger. L'intégration est très facile. Werkzeug permet en plus d'ouvrir un debugger interactif si le serveur d'application le permet. On regrettera cependant l'absence de variables locales et de couleurs.

traceback web avec werkzeug Traceback web avec werkzeug

Conclusion

Voici un tableau récapitulant les résultats des critères que nous avons observé sur les différents outils :

sentry ultratb backtrace colored-traceback pygments cgitb django werkzeug
couleur
contexte
variables locales
hook (pour CGI)
try except
module python ou interpréteur (bof)
lecture sur l'entrée standard
middleware WSGI
sortie texte
sortie html (mais hiddeuse)
projet très actif dans python peu soutenu
dédié à l'affichage de tracebacks
paquet pip (déjà dans python)

La conclusion que l'on peut tirer est qu'il n'existe pas d'outil remplissant tous les critères. ultratb semble être la meilleure option pour l'affichage en console, même s'il est embarqué dans IPython. Quant au monde du web, seul werkzeug semble sortir du lot, malgré qu'il ne soit pas dédié à la fonction d'afficher des tracebacks.

L'outil idéal pour mettre en forme des tracebacks, polyvalent, lisible et puissant, reste à développer. On peut cependant s'en tirer relativement correctement en utilisant ultratb pour l'affichage en terminal et werkzeug pour l'affichage web.

comments powered by Disqus