Jul 03, 2024

Wiki

Python

Aide

edit SideBar

Search

Logging


Le module logging permet de faire des logs. Ces logs peuvent avoir différents niveaux de détail, et différentes destinations : fichiers textes, mails, etc.

Source : Le PyMOTW de Doug Hellman.

Un premier exemple

Dans cette section, on montre comment écrire des logs dans un fichier. Pour ce faire, il faut placer ce bout de code dans un fichier, puis l'exécuter avec python :

  import logging
  FICHIER_LOG = '/tmp/log_exemple.log'
  logging.basicConfig(filename = FICHIER_LOG,
                      level = logging.DEBUG)
  logging.debug('Un message dans le fichir log')

Un fichier log_exemple.log apparaît alors dans /tmp, qui contient :

  $ more /tmp/log_exemple.log 
  DEBUG:root:Un message dans le fichir log

Si on relance une seconde fois le script, on trouve

  $ more /tmp/log_exemple.log 
  DEBUG:root:Un message dans le fichir log
  DEBUG:root:Un message dans le fichir log

Notons dès à présent qu'en l'absence de l'argument filename, les messages seront envoyés dans le terminal.

Utilisation avancée

Gérer plusieurs logs

Pour créer un nouveau fichier à chaque appel, un argument filemode = 'w' doit être passé au constructeur basicConfig(), comme suit :

  import logging
  FICHIER_LOG = '/tmp/log_exemple.log'
  logging.basicConfig(filename = FICHIER_LOG,
                      level = logging.DEBUG,
                      filemode = 'w')
  logging.debug('Un message dans le fichir log')

Le contenu du fichier log_exemple.log de /tmp est alors remplacé par :

  $ more /tmp/log_exemple.log 
  DEBUG:root:Un message dans le fichir log

Créer automatiquement plusieurs fichiers

Plutôt que de gérer soi-même la taille des fichiers logs, on peut préciser la taille maximale d'un tel fichier, avant la création d'un nouveau log. Pour cela, on doit utiliser RotatingFileHandler.

  #-*-coding:utf8-*-
  import logging
  import logging.handlers
  FICHIER_LOG = '/tmp/log_exemple.log'

  # On n'utilise plus une configuration de base, mais on crée à la main
  # son propre objet Logger
  mon_logger = logging.getLogger('MonLogger')
  mon_logger.setLevel(logging.DEBUG)

  # On précise alors combien d'octets chaque fichier peut contenir, et
  # combien de fichiers logs différents on autorise :
  handler = logging.handlers.RotatingFileHandler(FICHIER_LOG,
                                                 maxBytes = 20,
                                                 backupCount = 5)
  mon_logger.addHandler(handler)

  # Reste à remplir artificiellement les logs
  for i in range(20):
      mon_logger.debug('i = %d' % i)

Si on liste le contenu de /tmp, on s'aperçoit que plusieurs fichiers logs ont bien été créés...

  $ ls /tmp/log*
  /tmp/log_exemple.log    /tmp/log_exemple.log.2  /tmp/log_exemple.log.4
  /tmp/log_exemple.log.1  /tmp/log_exemple.log.3  /tmp/log_exemple.log.5

et qu'ils ne contiennent à chaque fois que le nombre spécifié d'octets...

  $ more /tmp/log_exemple.log.1
  k = 17
  k = 18

Pour le remplissage, la règle est la suivante :

  • On commence par log_exemple.log, c'est-à-dire le nom de fichier passé au constructeur RotatingFileHandler.
  • S'il atteint la taille limite, ce fichier est renomé en recevant le suffixe .1 (log_exemple.log.1), les nouveaux logs étant toujours écrits dans log_exemple.log.
  • Si ce dernier dépasse une fois encore la taille limite, alors log_exemple.log.1 est renomé log_exemple.log.2, log_exemple.log devient log_exemple.log.1, et on ouvre un nouveau log_exemple.log pour les logs à venir...

Différents messages

Le principe

Il existe différents niveaux de logs, avec des valeurs numériques associées :

  • CRITICAL 50
  • ERROR 40
  • WARNING 30
  • INFO 20
  • DEBUG 10
  • UNSET 0

On peut produire différents types de messages, avec différents niveaux d'importance, et décider de n'afficher (ou de n'enregistrer) que les messages supérieurs à un niveau donné.

Par exemple, si un message $m$ est de type WARNING, et qu'on a demandé au logger de n'afficher que des erreurs (niveaux supérieurs à 40), alors $m$ ne sera pas émis.

Illustration

Considérons le bout de code suivant...

  #-*-coding:utf8-*-
  import logging

  logging.basicConfig(level = logging.WARNING)

  logging.debug("Ceci est un message de deboguage")
  logging.info("Ceci est un message d'information")
  logging.warning("Ceci est un message d'alerte")
  logging.error("Ceci est un message d'erreur")
  logging.critical("Ceci est un message critique")

Il est constitué de 5 messages de log, chacun ayant un niveau différent. Au constructeur basicConfig, on a précisé que les messages émis doivent au moins être des alertes (donc tout message d'un niveau d'importance supérieur ou égal à l'alerte, à savoir l'alerte, l'erreur, et le critique).

Puisqu'aucun fichier n'est précisé au niveau du constructeur, l'émission se fera dans le terminal.

Après exécution, on y trouvera les messages suivants...

  WARNING:root:Ceci est un message d'alerte
  ERROR:root:Ceci est un message d'erreur
  CRITICAL:root:Ceci est un message critique

Hiérarchie de loggers

Jusqu'à présent, les logs émis contenaient tous root. Cela provient du fait que le module logging permet la création de différents objets logger, pouvant hériter les uns des autres, et possédant leurs noms propres.

Cela permet de préciser, dans le message, d'où provient le log (de quel package, par exemple) : il suffit de créer un nouvel objet à chaque fois qu'une origine est à distinguer.

Ainsi, le code suivant

  #-*-coding:utf8-*-
  import logging

  logging.basicConfig(level = logging.WARNING)

  logger1 = logging.getLogger('package1.module1')
  logger2 = logging.getLogger('package2.module2') 

  logger1.warning("Ce message provient d'un module")
  logger2.warning("ET ce message provient d'un autre module")

produit la sortie

  WARNING:package1.module1:Ce message provient d'un module
  WARNING:package2.module2:ET ce message provient d'un autre module

Chaque nouvel objet logger hérite de la configuration de son parent, et peut éventuellement être reconfiguré différement (changer le niveau d'alertes, par exemple).

Page Actions

Recent Changes

Group & Page

Back Links