Python Language
logging
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