ProgrammationDéveloppeur backend Python

Comment fonctionne la journalisation en Python via le module logging ? Quels niveaux de journalisation existent et comment configurer correctement un logger dans un projet multi-modules ? Donnez des exemples, expliquez les subtilités et les erreurs courantes.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Le module logging est l'outil standard de Python pour la journalisation. Il met en œuvre une hiérarchie de loggers et prend en charge les niveaux de journalisation (severity levels) : DEBUG, INFO, WARNING, ERROR, CRITICAL. Une utilisation correcte permet de gérer centralement la sortie, de sauvegarder les logs dans des fichiers, de les envoyer par email, de filtrer par niveau, etc.

L'idée principale est de créer des loggers avec des noms (logging.getLogger(__name__)) dans chaque module, sans créer de logger racine global à partir de zéro dans chaque endroit. La configuration (format, gestionnaires, niveau) se fait de manière centralisée au démarrage de l'application.

Exemple de configuration :

import logging logging.basicConfig(format='%(levelname)s:%(name)s:%(message)s', level=logging.INFO) logger = logging.getLogger(__name__) def foo(): logger.info('Message informatif') logger.error('Erreur !') foo()

Question piège.

Pourquoi ne peut-on pas appeler logging.basicConfig() dans chaque module ? Que se passera-t-il si l'on fait cela ?

Réponse : logging.basicConfig() configure le logger racine une seule fois par session Python. Les appels répétés, si le logger racine a déjà été initialisé, seront ignorés. En conséquence, si différents modules essaient d'appeler basicConfig() avec leurs propres formats/niveaux, seul le premier prendra effet !

Exemples d'erreurs réelles dues à l'ignorance des subtilités du sujet.


Histoire

Dans un grand projet, chaque développeur configurait la journalisation à sa manière via basicConfig et des gestionnaires locaux. À cause de cela, certains logs n'étaient pas du tout affichés, d'autres étaient dupliqués 10 fois, et les messages de différents modules ne tenaient pas dans un seul fichier.


Histoire

Lors de la migration d'un service web vers une journalisation multi-niveaux, on a oublié de spécifier le nom du logger via getLogger(__name__), on écrivait partout dans le logger racine. En conséquence, il était impossible de savoir d'où provenait un log spécifique.


Histoire

On utilisait la fonction logger.error() pour enregistrer tous les messages, même ceux qui n'étaient pas des erreurs. En conséquence, les systèmes de surveillance automatiques déclenchaient constamment des alertes, car ils voyaient un niveau élevé d'erreurs, alors qu'il s'agissait simplement de messages de debug/informationnels.