Ich habe mehrere Module, die das gleiche utils.py
-Paket verwenden. Wie kann ich den Logger in utils.py
unterscheiden, ohne die Logger-Variable von den Aufrufern (d. H. ClassA oder ClassB) übergeben zu müssen?Wie können Sie verschiedene Logger verwenden, ohne die Logger-Variable zu übergeben? (Python-Protokollierung)
Sehr einfache Beispielcodes sind wie folgt. In Wirklichkeit habe ich viele Funktionen und Klassen in utils.py
, und deshalb möchte ich die Variable logger
nicht in utils.py
übergehen.
~/test-two-loggers$ tree .
├── main.py
├── configs.py
├── ClassA.py
├── ClassB.py
└── utils.py
0 directories, 5 files
main.py
import ClassA
import ClassB
ClassA.func()
ClassB.func()
ClassA.py
import utils
import configs
import logging
def func():
logger = logging.getLogger("classA")
logger.info("in ClassA")
utils.common_func(logger) # I want to change this line!!!!
ClassB.py
import utils
import configs
import logging
def func():
logger = logging.getLogger("classB")
logger.info("in ClassB")
utils.common_func(logger) # I want to change this line!!!!
utils.py
def common_func(logger): # I want to change this line!!!!
# do a lot of things ClassA and ClassB both need to do
logger.info("in utils - step one finished")
# do a lot of things ClassA and ClassB both need to do
logger.info("in utils - step two finished")
# do a lot of things ClassA and ClassB both need to do
logger.info("in utils - step three finished")
configs.py
import logging.config
logging_config = {
"version": 1,
"formatters": {
"formatter_a": {
"format": u"[A][%(levelname)s] %(module)s.%(lineno)d: %(message)s"
},
"formatter_b": {
"format": u"[B][%(levelname)s] %(module)s.%(lineno)d: %(message)s"
},
},
"handlers": {
"console_a": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"formatter": "formatter_a",
"stream": "ext://sys.stdout"
},
"console_b": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"formatter": "formatter_b",
"stream": "ext://sys.stdout"
},
},
"loggers": {
"classA": {
"level": "DEBUG",
"handlers": ["console_a"],
"propagate": "no"
},
"classB": {
"level": "DEBUG",
"handlers": ["console_b"],
"propagate": "no"
},
},
}
logging.config.dictConfig(logging_config)
Ergebnis Ich möchte:
~/test-two-loggers$ python main.py
[A][INFO] ClassA.7: in ClassA
[A][INFO] utils.3: in utils - step one finished
[A][INFO] utils.5: in utils - step two finished
[A][INFO] utils.7: in utils - step three finished
[B][INFO] ClassB.7: in ClassB
[B][INFO] utils.3: in utils - step one finished
[B][INFO] utils.5: in utils - step two finished
[B][INFO] utils.7: in utils - step three finished
Aber ich will eine andere Lösung andere als dies. Ich möchte nicht die logger
Variable in utils
übergeben.
Sie haben hier ein bisschen Code riechen. Wenn Sie ein Dienstprogramm-Modul haben, scheint es, als ob Sie von dem Dienstprogramm-Namespace protokollieren sollten. Wenn Sie einen Grund haben, den Stack-Trace zu verwenden, können Sie einfach Ihren eigenen Formatierer erstellen (https://github.com/python/cpython/blob/5b5fb38cc70122354c95f0a88cacaffab7d0b523/Lib/logging/__init__.py#L514). um herauszufinden, woher es hieß. –
@WayneWerner 'Wenn Sie ein Dienstprogramm-Modul haben, scheint es, als ob Sie aus dem Dienstprogramm-Namespace protokollieren sollten. Aber das Log-In-Dienstprogramm wird ohne den Kontext weniger aussagekräftig sein (ob es von ClassA oder ClassB kommt, wenn ein Fehler im Dienstprogramm auftritt, welcher Aufrufer war und was zuvor in ClassA oder ClassB getan wurde, bevor das Dienstprogramm aufgerufen wurde). Aber ich denke, das ist auch eine Philosophie, die wir ausprobieren können. Vielleicht können wir die Anmeldung in einem Dienstprogramm unabhängig machen und Protokolle in Klasse A/B hinzufügen, um die Ergebniszusammenfassung im Dienstprogramm anzuzeigen. Das ist sicher eine Option. –
Das ist definitiv meine Vorliebe - das Überarbeiten deiner App, um durch merkwürdige Holzrahmen zu springen, ist selten eine gute Idee. Sie können auch den Fn-Aufruf in ein try/except-Wrapping umbrechen und 'logger.exception ('problem with utility') 'verwenden und das traceback even mit einschließen. Das ist ein praktischer Weg, um außergewöhnlichen Fällen zu begegnen. –