Das Logging-Modul in Python

Protokolliert

Auch für selbst geschriebene Skripts bieten sich Logging-Frameworks an, mit denen sich Programmmeldungen in Log-Dateien umlenken lassen. Für Python-Entwickler gibt es dazu das Logging-Modul, das dieser Artikel näher vorstellt.
Mit E-Mail-Diensten muss sich jeder Administrator früher oder später einmal beschäftigen. Das zur CeBIT erscheinende ADMIN 02/2012 gibt dazu Praxis-Tipps und ... (mehr)

Wie oft baut man in eigene Programme und Skripts mal ein Print-Statement ein, weil etwas nicht wie gewollt funktioniert und man nachschauen will, was eigentlich passiert? Etwas geschickter ist es dabei schon, eine eigene Funktion zu verwenden, die abhängig von einem Schalter solche Meldungen ausgibt oder unterdrückt. All dies ist aber eigentlich unnötig, denn es gibt bei Python ein leistungsfähiges Logging-Modul, das sich für solche Zwecke anbietet. Zum Beispiel bei Webprojekten kann es die Entwicklung stark vereinfachen, weil dann meist kein Standardausgabekanal zur Verfügung steht und sich die Programmausgaben stattdessen leicht ins Syslog umleiten lassen.

Geschrieben hat es Vinay Sajip, der das Konzept im Python-Standarddokument PEP 282 dargelegt [1] und die Implementation auf einer eigenen Webseite dokumentiert hat [2]. Dabei hat er sich schon vor dem Programmieren viele Gedanken gemacht und sich unter anderem von Javas Log4j inspirieren lassen. Mit Python 2.3 wurde das Logging-Modul [3] schließlich in die Standard Library aufgenommen. Deshalb gibt es im Normalfall auch nichts zu installieren, wenn auf dem Rechner bereits eine aktuelle Python-Distribution installiert ist.

Um das Modul zu verwenden, importieren Sie es zu Beginn eines Skripts mit

import logging

Es stellt statische Funktionen wie »debug« , »info« und »warning« bereit, über die sich Informationen unterschiedlicher Logging-Level ausgeben lassen. Das Prinzip ist vielleicht von Unix/Linux-Daemons wie Apache und dem dazugehörigen Syslog-Daemon bekannt.

So ist Debug das höchste Level, das alle darunterliegenden Level wie Notice und Error einschließt. Ist das Logging-Level Debug ausgewählt, bekommt der Anwender alle Informationen zu sehen, die überhaupt ausgegeben werden. Das Log-Level Warning schließt Debug-Meldungen aus, beinhaltet aber immer noch alle Fehlermeldungen (Error). Das Python-Modul implementiert aber nicht alle Level des Unix-Syslog, sondern beschränkt sich pragmatischerweise auf fünf, die Tabelle 1 mit ihrem jeweiligen Einsatzzweck zeigt. Bei Bedarf lassen sich aber auch eigene Log-Level definieren.

Steuerung per Log-Level

Wählt man das Log-Level Error, beschränkt sich ein Programm auf die Ausgabe von Fehlern und gibt keine anderen Meldungen aus. Die folgenden Anweisungen in einem Python-Skript veranschaulichen das:

logging.debug('nur bei der Fehlersuche')
logging.info('eine informative Meldung')
logging.warning('eine Warnung')

Wer diese Zeilen in einem Skript ausführt, bekommt per Default nur die Warnung zu sehen. Um die anderen Meldungen zu sehen, muss man im Skript erst über die passende Methode des Logging-Moduls das Log-Level höher setzen:

logging.basicConfig(level=logging.DEBUG)

Wie man sieht, stellt das Logging-Modul jeder Meldung das Logging-Level in Großbuchstaben voran. Wer das Level nun per Kommandozeilenargument übergibt und im eigenen Skript verarbeitet, kann beim Aufruf steuern, wie gesprächig das eigene Programm ist.

Auf einfache Weise lässt sich »basicConfig« auch dazu verwenden, eine Log-Datei anzugeben. Dazu verarbeitet die Funktion den optionalen Parameter »filename« , etwa:

logging.basicConfig(filename='debug.log')

Die Funktion »basicConfig« versteht darüber hinaus die sechs Parameter »filename« , »filemode« (zum Beispiel zum Anhängen statt Überschreiben), »format« , »datefmt« , »level« und »stream« . Mit »format« können Sie das Format der Log-Meldungen verändern. Zum Beispiel entfernen Sie den String »root« (des sogenannten Root-Loggers, dazu gleich mehr), der in den Standardmeldungen enthalten war, indem Sie folgendes Format einstellen:

logging.basicConfig(format='%(levelname)s:%(message)s')

Als Variablen stehen dabei alle Attribute der Klasse »LogRecord« zur Verfügung, zum Beispiel verschiedene Zeitstempel, Informationen über den laufenden Prozess und die Threads, das Modul, die aktuelle Funktion und die Zeilennummer im Skript.

Strukturiert

Statt die statischen Funktionen der Logging-Klasse aufzurufen, können Sie auch das objektorientierte Interface mit Logger-Objekten verwenden. Damit strukturieren Sie bei größeren Projekten das Logging besser und zum Beispiel nach Programmmodulen getrennt. Dazu lassen Sie sich vom Modul mit »getLogger« einen Logger geben, mit dem Sie anschließend weiterarbeiten. Der String in Klammern gibt den Namespace an. Mit Punkten abgetrennt, ähnlich wie bei Java- und Python-Klassen, können Sie so das Logging für eigene Programmmodule strukturieren und eine Baumstruktur von Loggern aufbauen. Ein Beispiel dafür gibt Listing 1. Zu Beginn des Skripts müssen Sie erst »basicConfig« aufrufen, sonst erhalten Sie keinen Logger. An der Wurzel des Baums befindet sich per Default stets der sogenannte Root-Logger.

Listing 1

Logging mit getLogger()

 

Die Logger besitzen Methoden mit den gleichen Namen wie das Modul, also »debug« , »info« , »warning« , »error« und »critical« , das Loglevel lässt sich dann für jeden Logger einstellen, wie Listing 1 zeigt. Wenn Sie in verschiedenen Modulen eines Programms mehrfach »getLogger« aufrufen, erhalten Sie immer die gleiche Referenz auf den Logger. Die Dokumentation weist übrigens darauf hin, dass man in Python-Versionen kleiner 2.7.1 respektive 3 Vorsicht bei der Anwendung der statischen Modulfunktionen walten lassen sollte, wenn man Threads verwendet. Unter ungünstigen Umständen werden Handler dabei doppelt angelegt.

Ähnliche Artikel

comments powered by Disqus

Artikel der Woche

Eigene Registry für Docker-Images

Wer selber Docker-Images herstellt, braucht auch eine eigene Registry. Diese gibt es ebenfalls als Docker-Image, aber nur mit eingeschränkter Funktionalität. Mit einem Auth-Server wird daraus ein brauchbares Repository für Images. (mehr)
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Konfigurationsmanagement

Ich konfiguriere meine Server

  • von Hand
  • mit eigenen Skripts
  • mit Puppet
  • mit Ansible
  • mit Saltstack
  • mit Chef
  • mit CFengine
  • mit dem Nix-System
  • mit Containern
  • mit anderer Konfigurationsmanagement-Software

Google+

Ausgabe /2019