405 Stimmen

Die Verwendung von Protokollierung in mehreren Modulen

Ich habe ein kleines Python-Projekt mit folgender Struktur -

Projekt 
 -- pkg01
   -- test01.py
 -- pkg02
   -- test02.py
 -- logging.conf

Ich plane, das Standard-Logging-Modul zu verwenden, um Nachrichten sowohl auf stdout als auch in eine Protokolldatei zu drucken. Um das Logging-Modul zu verwenden, ist eine Initialisierung erforderlich -

import logging.config

logging.config.fileConfig('logging.conf')
logger = logging.getLogger('pyApp')

logger.info('testing')

Derzeit führe ich diese Initialisierung in jedem Modul durch, bevor ich Log-Nachrichten protokolliere. Ist es möglich, diese Initialisierung nur einmal an einem Ort durchzuführen, so dass die gleichen Einstellungen im gesamten Projekt wiederverwendet werden?

442voto

Vinay Sajip Punkte 89444

Die bewährte Praxis ist, in jedem Modul einen Logger wie folgt zu definieren:

import logging
logger = logging.getLogger(__name__)

in der Nähe des oberen Bereichs des Moduls, und dann im anderen Code im Modul z.B.

logger.debug('Meine Nachricht mit %s', 'Variablendaten')

Wenn Sie die Protokollierungsaktivität innerhalb eines Moduls unterteilen müssen, verwenden Sie z.B.

loggerA = logging.getLogger(__name__ + '.A')
loggerB = logging.getLogger(__name__ + '.B')

und protokollieren Sie bei Bedarf mit loggerA und loggerB.

In Ihrem Hauptprogramm oder Programmen tun Sie z.B.:

def main():
    "Ihr Programmcode"

if __name__ == '__main__':
    import logging.config
    logging.config.fileConfig('/pfad/zu/logging.conf')
    main()

oder

def main():
    import logging.config
    logging.config.fileConfig('/pfad/zu/logging.conf')
    # Ihr Programmcode

if __name__ == '__main__':
    main()

Siehe hier für das Protokollieren aus mehreren Modulen und hier für die Protokollierungskonfiguration für Code, der als Bibliotheksmodul von anderem Code verwendet wird.

Aktualisierung: Beim Aufruf von fileConfig() möchten Sie möglicherweise disable_existing_loggers=False angeben, wenn Sie Python 2.6 oder höher verwenden (siehe die Dokumentation für weitere Informationen). Der Standardwert ist True für Abwärtskompatibilität, was bewirkt, dass alle vorhandenen Logger durch fileConfig() deaktiviert werden, es sei denn, sie oder ihre Vorgänger sind explizit in der Konfiguration benannt. Mit dem Wert False bleiben vorhandene Logger unberührt. Wenn Sie Python 2.7/Python 3.2 oder höher verwenden, sollten Sie die dictConfig()-API in Betracht ziehen, die besser als fileConfig() ist, da sie mehr Kontrolle über die Konfiguration bietet.

264voto

Stan Prokop Punkte 4853

Eigentlich ist jeder Logger ein Kind des Eltern-Paketloggers (d.h. Paket.Unterpaket.Modul erbt die Konfiguration von Paket.Unterpaket), daher müssen Sie nur den Root-Logger konfigurieren. Dies kann erreicht werden durch logging.config.fileConfig (Ihr eigene Konfiguration für Logger) oder logging.basicConfig (setzt den Root-Logger). Richten Sie das Logging in Ihrem Einstiegsmodule ein (__main__.py oder was auch immer Sie ausführen möchten, z.B. main_script.py. __init__.py funktioniert auch)

Verwendung von basicConfig:

# package/__main__.py
import logging
import sys

logging.basicConfig(stream=sys.stdout, level=logging.INFO)

Verwendung von fileConfig:

# package/__main__.py
import logging
import logging.config

logging.config.fileConfig('logging.conf')

und dann erstellen Sie jeden Logger mit:

# package/untermodul.py
# oder
# package/unterpaket/untermodul.py
import logging
log = logging.getLogger(__name__)

log.info("Hallo Logging!")

Weitere Informationen finden Sie in Erweitertes Logging-Tutorial.

56voto

Alex Jolig Punkte 12486

Ein einfacher Weg, um eine Instanz der Logging-Bibliothek in mehreren Modulen zu verwenden, war für mich die folgende Lösung:

base_logger.py

import logging

logger = logging
logger.basicConfig(format='%(asctime)s - %(message)s', level=logging.INFO)

Andere Dateien

from base_logger import logger

if __name__ == '__main__':
    logger.info("Dies ist eine Infomeldung")

16voto

Yarkee Punkte 8394

Ich mache es immer so wie unten.

Verwenden Sie eine einzige Python-Datei, um mein Protokoll als Singleton-Muster zu konfigurieren, das 'log_conf.py' genannt wird.

#-*-coding:utf-8-*-

import logging.config

def singleton(cls):
    instances = {}
    def get_instance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return get_instance()

@singleton
class Logger():
    def __init__(self):
        logging.config.fileConfig('logging.conf')
        self.logr = logging.getLogger('root')

In einem anderen Modul einfach die Konfiguration importieren.

from log_conf import Logger

Logger.logr.info("Hallo Welt")

Dies ist ein Singleton-Muster zum Protokollieren, einfach und effizient.

14voto

Tommy Punkte 11107

Wirf noch eine weitere Lösung ein.

In meiner init.py-Datei des Moduls habe ich etwas Ähnliches wie:

# mymodule/__init__.py
import logging

def get_module_logger(mod_name):
  logger = logging.getLogger(mod_name)
  handler = logging.StreamHandler()
  formatter = logging.Formatter(
        '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
  handler.setFormatter(formatter)
  logger.addHandler(handler)
  logger.setLevel(logging.DEBUG)
  return logger

Dann in jedem Modul, für das ich einen Logger benötige, mache ich Folgendes:

# mymodule/foo.py
from [modname] import get_module_logger
logger = get_module_logger(__name__)

Wenn die Protokolle fehlen, können Sie ihre Quelle anhand des Moduls unterscheiden, aus dem sie stammen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X