Zoeken…


Introductie tot Python Logging

Deze module definieert functies en klassen die een flexibel gebeurtenisregistratiesysteem voor applicaties en bibliotheken implementeren.

Het belangrijkste voordeel van de logboek-API die door een standaardbibliotheekmodule wordt geleverd, is dat alle Python-modules kunnen deelnemen aan logboekregistratie, zodat uw toepassingslogboek uw eigen berichten kan bevatten die zijn geïntegreerd met berichten van modules van derden.

Dus laten we beginnen:

Voorbeeldconfiguratie rechtstreeks in 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')

Uitvoervoorbeeld:

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

Voorbeeldconfiguratie via een INI-bestand

Ervan uitgaande dat het bestand logging_config.ini heet. Meer details voor het bestandsformaat zijn in de logging configuratie deel van de logging zelfstudie .

[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

Gebruik vervolgens logging.config.fileConfig() in de 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')

Voorbeeldconfiguratie via een woordenboek

Vanaf Python 2.7 kunt u een woordenboek met configuratiegegevens gebruiken. PEP 391 bevat een lijst met verplichte en optionele elementen in het configuratiewoordenboek.

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')

Uitzonderingen voor logboekregistratie

Als u uitzonderingen wilt loggen, kunt en moet u gebruik maken van de methode 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

Geef de uitzondering niet door als argument:

Omdat logging.exception(msg) een msg arg verwacht, is het een veel voorkomende valkuil om de uitzondering als volgt in de logging-oproep door te geven:

>>> 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

Hoewel het misschien lijkt alsof dit in het begin het juiste is om te doen, is het eigenlijk problematisch vanwege de reden hoe uitzonderingen en verschillende codering samenwerken in de logboekmodule:

>>> 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

Probeert een uitzondering te loggen die unicode-tekens bevat, op deze manier zal het jammerlijk mislukken . Het verbergt de stacktrace van de oorspronkelijke uitzondering door deze te vervangen door een nieuwe die naar logging.exception(e) komt tijdens het formatteren van uw logging.exception(e) .

Het is duidelijk dat u zich in uw eigen code mogelijk bewust bent van de codering in uitzonderingen. Bibliotheken van derden kunnen hier echter op een andere manier mee omgaan.

Correct gebruik:

Als je in plaats van de uitzondering gewoon een bericht doorgeeft en python zijn magie laat doen, zal het werken:

>>> 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

Zoals je kunt zien, gebruiken we in dat geval eigenlijk e niet, de aanroep naar logging.exception(...) magische wijze de meest recente uitzondering op.

Logboekuitzonderingen met niet-ERROR-logboekniveaus

Als u een uitzondering wilt loggen met een ander exc_info dan ERROR, kunt u het argument exc_info van de standaardloggers gebruiken:

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

Toegang tot het bericht van de uitzondering

Houd er rekening mee dat bibliotheken daar uitzonderingen met berichten kunnen veroorzaken, zoals unicode of (utf-8 als je geluk hebt) byte-strings. Als u echt toegang moet hebben tot de tekst van een uitzondering, is de enige betrouwbare manier, die altijd zal werken, repr(e) of de %r -stringopmaak te gebruiken:

>>> 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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow