Suche…


Einführung in die Python-Protokollierung

Dieses Modul definiert Funktionen und Klassen, die ein flexibles Ereignisprotokollierungssystem für Anwendungen und Bibliotheken implementieren.

Der Hauptvorteil der Protokollierungs-API, die von einem Standardbibliotheksmodul bereitgestellt wird, besteht darin, dass alle Python-Module an der Protokollierung teilnehmen können, sodass Ihr Anwendungsprotokoll Ihre eigenen Nachrichten enthalten kann, die in Nachrichten von Drittanbieter-Modulen integriert sind.

So lass uns anfangen:

Beispielkonfiguration direkt im 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')

Ausgabebeispiel:

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

Beispielkonfiguration über eine INI-Datei

Angenommen, die Datei heißt logging_config.ini. Weitere Informationen zum Dateiformat finden Sie im Logging-Konfigurationsabschnitt des Logging-Lernprogramms .

[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

Verwenden logging.config.fileConfig() dann logging.config.fileConfig() im 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')

Beispielkonfiguration über ein Wörterbuch

Ab Python 2.7 können Sie ein Wörterbuch mit Konfigurationsdetails verwenden. PEP 391 enthält eine Liste der obligatorischen und optionalen Elemente im Konfigurationswörterbuch.

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

Ausnahmen für die Protokollierung

Wenn Sie Ausnahmen protokollieren möchten, können und sollten Sie die Methode logging.exception(msg) verwenden:

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

Übergeben Sie die Ausnahme nicht als Argument:

Da logging.exception(msg) ein msg logging.exception(msg) erwartet, ist es eine häufige Gefahr, die Ausnahme wie folgt an den Protokollierungsaufruf zu übergeben:

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

Es sieht zwar so aus, als wäre dies anfangs das Richtige, aber es ist problematisch, weil Ausnahmen und verschiedene Codierungen im Protokollierungsmodul zusammenarbeiten:

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

Beim Versuch, eine Ausnahme zu protokollieren, die Unicode-Zeichen enthält, schlägt dieser Weg fehl . logging.exception(e) wird der Stacktrace der ursprünglichen Ausnahme logging.exception(e) indem sie durch eine neue überschrieben wird, die während der Formatierung des logging.exception(e) von logging.exception(e) .

Natürlich kennen Sie in Ihrem eigenen Code die Kodierung in Ausnahmen. Drittanbieter-Bibliotheken können dies jedoch auf andere Weise behandeln.

Richtige Benutzung:

Wenn Sie statt der Ausnahme einfach eine Nachricht übergeben und Python seine Magie anwenden lassen, funktioniert es:

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

Wie Sie sehen, verwenden wir in diesem Fall nicht e , und der Aufruf von logging.exception(...) formatiert die jüngste Ausnahme magisch.

Protokollierung von Ausnahmen mit Nicht-FEHLER-Protokollierungsstufen

Wenn Sie eine Ausnahme mit einer anderen Protokollebene als ERROR protokollieren möchten, können Sie das Argument exc_info der Standardprotokollierer verwenden:

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

Zugriff auf die Nachricht der Ausnahme

Beachten Sie, dass Bibliotheken da draußen Ausnahmen mit Meldungen als Unicode oder (utf-8, wenn Sie Glück haben) Byte-Zeichenfolgen auslösen können. Wenn Sie wirklich auf den Text einer Ausnahme zugreifen müssen, ist die einzige zuverlässige Methode, die immer funktioniert, die Verwendung von repr(e) oder der Zeichenfolge %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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow