Recherche…


Introduction à la journalisation Python

Ce module définit des fonctions et des classes qui implémentent un système flexible de journalisation des événements pour les applications et les bibliothèques.

Le principal avantage de disposer de l'API de journalisation fournie par un module de bibliothèque standard est que tous les modules Python peuvent participer à la journalisation. Votre journal d'application peut donc inclure vos propres messages intégrés à des messages provenant de modules tiers.

Alors, commençons:

Exemple de configuration directement dans le code

import logging

logger = logging.getLogger()
handler = logging.StreamHandler()
formatter = logging.Formatter(
        '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)

logger.debug('this is a %s test', 'debug')

Exemple de sortie:

2016-07-26 18:53:55,332 root         DEBUG    this is a debug test

Exemple de configuration via un fichier INI

En supposant que le fichier s'appelle logging_config.ini. Plus de détails sur le format de fichier se trouvent dans la section de configuration de la journalisation du didacticiel de journalisation .

[loggers]
keys=root

[handlers]
keys=stream_handler

[formatters]
keys=formatter

[logger_root]
level=DEBUG
handlers=stream_handler

[handler_stream_handler]
class=StreamHandler
level=DEBUG
formatter=formatter
args=(sys.stderr,)

[formatter_formatter]
format=%(asctime)s %(name)-12s %(levelname)-8s %(message)s

Ensuite, utilisez logging.config.fileConfig() dans le code:

import logging
from logging.config import fileConfig

fileConfig('logging_config.ini')
logger = logging.getLogger()
logger.debug('often makes a very good meal of %s', 'visiting tourists')

Exemple de configuration via un dictionnaire

A partir de Python 2.7, vous pouvez utiliser un dictionnaire avec des détails de configuration. Le PEP 391 contient une liste des éléments obligatoires et facultatifs du dictionnaire de configuration.

import logging
from logging.config import dictConfig

logging_config = dict(
    version = 1,
    formatters = {
        'f': {'format':
              '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'}
        },
    handlers = {
        'h': {'class': 'logging.StreamHandler',
              'formatter': 'f',
              'level': logging.DEBUG}
        },
    root = {
        'handlers': ['h'],
        'level': logging.DEBUG,
        },
)

dictConfig(logging_config)

logger = logging.getLogger()
logger.debug('often makes a very good meal of %s', 'visiting tourists')

Exceptions de journalisation

Si vous souhaitez enregistrer des exceptions, vous pouvez et devez utiliser la logging.exception(msg) :

>>> import logging
>>> logging.basicConfig()
>>> try:
...     raise Exception('foo')
... except:
...     logging.exception('bar')
...
ERROR:root:bar
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
Exception: foo

Ne passez pas l'exception en tant qu'argument:

Comme logging.exception(msg) attend un argument msg , il est courant de passer l'exception dans l'appel de journalisation comme ceci:

>>> try:
...     raise Exception('foo')
... except Exception as e:
...     logging.exception(e)
...
ERROR:root:foo
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
Exception: foo

Bien que cela puisse sembler être la bonne chose à faire au début, il est en réalité problématique en raison de la façon dont les exceptions et divers codages fonctionnent ensemble dans le module de journalisation:

>>> try:
...     raise Exception(u'föö')
... except Exception as e:
...     logging.exception(e)
...
Traceback (most recent call last):
  File "/.../python2.7/logging/__init__.py", line 861, in emit
    msg = self.format(record)
  File "/.../python2.7/logging/__init__.py", line 734, in format
    return fmt.format(record)
  File "/.../python2.7/logging/__init__.py", line 469, in format
    s = self._fmt % record.__dict__
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-2: ordinal not in range(128)
Logged from file <stdin>, line 4

En essayant de connecter une exception contenant des caractères unicode, cette méthode échouera lamentablement . Il masquera le stacktrace de l'exception d'origine en le remplaçant par un nouveau qui est logging.exception(e) lors du formatage de votre logging.exception(e) .

De toute évidence, dans votre propre code, vous pourriez avoir connaissance de l'encodage des exceptions. Cependant, les bibliothèques tierces peuvent gérer cela différemment.

Usage correct:

Si au lieu de l'exception il suffit de passer un message et de laisser python faire sa magie, cela fonctionnera:

>>> try:
...     raise Exception(u'föö')
... except Exception as e:
...     logging.exception('bar')
...
ERROR:root:bar
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
Exception: f\xf6\xf6

Comme vous pouvez le voir, nous n'utilisons pas e dans ce cas, l'appel à logging.exception(...) formate comme par magie l'exception la plus récente.

Journalisation des exceptions avec des niveaux de journal non ERROR

Si vous souhaitez enregistrer une exception avec un autre niveau de journal que ERROR, vous pouvez utiliser l'argument exc_info des enregistreurs par défaut:

logging.debug('exception occurred', exc_info=1)
logging.info('exception occurred', exc_info=1)
logging.warning('exception occurred', exc_info=1)

Accéder au message de l'exception

Sachez que les bibliothèques peuvent générer des exceptions avec des messages comme n'importe quelle chaîne de caractères unicode ou (utf-8 si vous êtes chanceux). Si vous avez vraiment besoin d'accéder au texte d'une exception, le seul moyen fiable, qui fonctionnera toujours, est d'utiliser repr(e) ou le formatage de la chaîne %r :

>>> try:
...     raise Exception(u'föö')
... except Exception as e:
...     logging.exception('received this exception: %r' % e)
...
ERROR:root:received this exception: Exception(u'f\xf6\xf6',)
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
Exception: f\xf6\xf6


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow