Sök…


Introduktion till Python Logging

Den här modulen definierar funktioner och klasser som implementerar ett flexibelt händelseloggningssystem för applikationer och bibliotek.

Den viktigaste fördelen med att ha loggnings-API som tillhandahålls av en standardbiblioteksmodul är att alla Python-moduler kan delta i loggningen, så din applikationslogg kan inkludera dina egna meddelanden integrerade med meddelanden från tredjepartsmoduler.

Så låt oss börja:

Exempel på konfiguration direkt i kod

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

Utgångsexempel:

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

Exempel på konfiguration via en INI-fil

Förutsatt att filen heter logging_config.ini. Mer information om filformatet är i loggningskonfiguration delen av loggnings handledning .

[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

logging.config.fileConfig() i koden:

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

Exempel på konfiguration via en ordlista

Från Python 2.7 kan du använda en ordlista med konfigurationsdetaljer. PEP 391 innehåller en lista över obligatoriska och valfria element i konfigurationsordlistan.

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

Loggningsundantag

Om du vill logga undantag kan du och bör använda 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

Passera inte undantaget som argument:

Eftersom logging.exception(msg) förväntar sig ett msg arg, är det en vanlig fallgrop att överföra undantaget till loggningssamtalet så här:

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

Det kan se ut som om det här är rätt att göra i början, men det är faktiskt problematiskt på grund av att undantag och olika kodningar fungerar tillsammans i loggmodulen:

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

Om du försöker logga ett undantag som innehåller unicode-tecken, kommer detta sätt att misslyckas . Det kommer att dölja stacktracket för det ursprungliga undantaget genom att åsidosätta det med ett nytt som höjs under formateringen av ditt logging.exception(e) -samtal.

Uppenbarligen i din egen kod kanske du känner till kodningen i undantag. Emellertid kan bibliotek från tredje part hantera detta på ett annat sätt.

Rätt användning:

Om du istället för undantaget bara skickar ett meddelande och låter python göra sin magi, fungerar det:

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

Som ni ser använder vi faktiskt inte e i så fall, logging.exception(...) samtalet till logging.exception(...) magiskt det senaste undantaget.

Loggningsundantag med icke ERROR-loggnivåer

Om du vill logga ett undantag med en annan loggnivå än ERROR, kan du använda exc_info argumentet för standardloggarna:

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

Få åtkomst till undantagets meddelande

Var medveten om att bibliotek där ute kan kasta undantag med meddelanden som någon av unicode eller (utf-8 om du har tur) byte-strängar. Om du verkligen behöver komma åt ett undantags text, är det enda pålitliga sättet, som alltid fungerar, att använda repr(e) eller %r strängen formatering:

>>> 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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow