Logging

Das logging-Modul ist Teil der Python-Standardbibliothek. Es ist beschrieben in PEP 0282. Eine erste Einführung in das Modul erhaltet ihr in Basic Logging Tutorial.

Alternativ könnt ihr auch loguru verwenden, das Logging fast so einfach wie print-Anweisungen macht.

Logging erfüllt üblicherweise zwei verschiedene Zwecke:

Diagnose:

  • Ihr könnt euch den Kontext von bestimmten Ereignissen anzeigen lassen.

  • Tools wie Sentry gruppieren zusammengehörende Ereignisse, erleichtern die Benutzeridentifikation etc. sodass Entwickler die Fehlerursache schneller finden können.

Monitoring:

  • Das Logging zeichnet Ereignisse für benutzerdefinierten Heuristiken, z.B. für Geschäftsanalysen, auf. Diese Aufzeichnungen können für Berichte oder Optimierungen der Geschäftsziele verwendet und ggf. visualisiert werden.

Welche Vorteile bietet logging nun gegenüber print?

  • Die Logdatei enthält alle verfügbaren Diagnoseinformationen wie Dateiname, Pfad, Funktion und Zeilennummer

  • Alle Ereignisse sind über den Root-Logger automatisch verfügbar, sofern Sie sie nicht explizit herausgefiltert werden.

  • Logging kann wahlweise durch eine der folgenden beiden Methoden stummgeschaltet werden: logging.Logger.setLevel() oder logging.disabled.

[1]:
import logging

Beispielkonfiguration über eine INI-Datei

Im folgenden Beispiel wird die Datei development.ini in diesem Verzeichnis geladen:

[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
[2]:
from logging.config import fileConfig
[3]:
fileConfig('development.ini')
d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
logger = logging.getLogger('tcpserver')
logger.warning('Protocol problem: %s', 'connection reset', extra=d)
2019-10-21 16:25:30,681 tcpserver    WARNING  Protocol problem: connection reset

Pro:

  • Möglichkeit, die Konfiguration während des Betriebs zu aktualisieren indem die Funktion logging.config.listen() verwendet wird um an einem Socket zu lauschen.

  • In verschiedenen Umgebungen können unterschiedliche Konfigurationen verwendet werden, also z.B. kann in der development.ini DEBUG als Log-Level angegeben werden während in der production.ini WARN verwendet wird.

Con:

  • Weniger Kontrolle z.B. gegenüber benutzerdefinierten Filtern oder Logger, die im Code konfiguriert sind.

Beispielkonfiguration über ein Dictionary

[4]:
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)

Pro:

  • Aktualisieren während des Betriebs

Con:

  • Weniger Kontrolle als beim Konfigurieren eines Loggers im Code

Beispielkonfiguration direkt im Code

[5]:
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)

Alternativ könnt ihr auch Magic Commands verwenden:

Befehl

Beschreibung

%logstart

Startet das Logging irgendwo in einer Session

%logstart [-o\|-r\|-t\|-q] [log_name [log_mode]]

Wenn kein Name angegeben wird, wird ipython_log.py im aktuellen Verzeichnis verwendet.

log_mode ist ein optionaler Parameter. Folgende Modi können angegeben werden:

* append hängt die Logging-Informationen am Ende einer vorhandenen Datei an

* backup benennt die vorhandene Datei um in name~ und schreibt in name

* global hängt die Logging-Informationen am Ende einer vorhandenen Datei im

* over überschreibt eine existierende Log-Datei

* rotate erstellt rotierende Log-Dateien: name.1~, name.2~, etc.

Optionen:

* -o logt auch den Output von IPython

* -r logt raw Output

* -t schreibt einen Zeitstempel vor jeden Logeintrag

* -q unterdrückt die Logging-Ausgabe

%logon

Neustart des Logging

%logoff

Temporäres Beenden des Logging

Pro:

  • Vollständige Kontrolle über die Konfiguration

Con:

  • Änderungen in der Konfiguration erfordern eine Änderung des Quellcodes