4 votes

Comment faire en sorte que le décorateur de journalisation enregistre le nom de fichier là où il est utilisé et non pas là où il est défini ?

J'utilise le logging avec le module filename pour capturer la sortie du journal de mon code. Cela fonctionne bien, car je sais maintenant toujours à partir de quel fichier le message a été envoyé. Cependant, j'ai un décorateur de journalisation indenté pour lequel j'aimerais enregistrer le nom de fichier à l'endroit où il a été envoyé. est utilisé et non le module où le décorateur est défini . Est-ce possible ?

Voici un bref exemple de ce qu'il fait actuellement :

test.py

import logging
from log import logger
from log import indented

@indented('Here I start my method...', 'And here it ends')
def my_func():
    logger.info('Look, a message!')

if __name__ == '__main__':
    logging.basicConfig(
        filename='LOG',
        level=logging.DEBUG,
        format='%(asctime)s.%(msecs)03d [ %(levelname)-8s] %(filename)s: %(message)s',
        datefmt="%Y-%m-%d %H:%M:%S")
    my_func()

Sortie du journal

2018-07-27 13:27:15.541 [ INFO    ] log.py: Here I start my method...
2018-07-27 13:27:15.541 [ INFO    ] test.py: ---- Look, a message!
2018-07-27 13:27:15.541 [ INFO    ] log.py: And here it ends

Je voudrais maintenant que les trois messages contiennent test.py comme suit :

Résultats souhaités

2018-07-27 13:27:15.541 [ INFO    ] test.py: Here I start my method...
2018-07-27 13:27:15.541 [ INFO    ] test.py: ---- Look, a message!
2018-07-27 13:27:15.541 [ INFO    ] test.py: And here it ends

log.py

import logging
from contextlib import contextmanager
from functools import wraps

class IndentationAdapter(logging.LoggerAdapter):
    def __init__(self, logger, extra):
        super().__init__(logger, extra)
        self._indent = 0

    def indent(self):
        self._indent += 4

    def dedent(self):
        self._indent -= 4

    def process(self, msg, kwargs):
        if self._indent > 0:
            return '{i} {m}'.format(i='-'*self._indent, m=msg), kwargs
        else:
            return msg, kwargs

logger = IndentationAdapter(logging.getLogger(), {})

@contextmanager
def indent_logging():
    logger.indent()
    try:
        yield
    finally:
        logger.dedent()

def indented(begin_message, end_message):
    def indent_decorator(func):
        @wraps(func)
        def func_wrapper(*args, **kwargs):
            logger.info(begin_message)
            with indent_logging():
                output = func(*args, **kwargs)
            logger.info(end_message)

            return output

        return func_wrapper
    return indent_decorator

1voto

Kenny Ostrom Points 2815

J'ai pu automatiser les messages de nom de fichier et de début/fin en copiant une partie de l'inspection du code utilisée par le module de journalisation de la bibliothèque standard. J'ai supprimé les messages manuels de début et de fin, pensant que c'était plus votre intention. J'ai également supprimé le nom de fichier du format de journalisation, et l'ai ajouté dans le texte journalisé par l'indent_decorator.

    def indented():
        def indent_decorator(func):
            @wraps(func)
            def func_wrapper(*args, **kwargs):
                filename = os.path.basename(func.__code__.co_filename)
                logger.info(filename + ': begin ' + func.__name__)
                with indent_logging():
                    output = func(*args, **kwargs)
                logger.info(filename + ': end ' + func.__name__)

                return output

            return func_wrapper
        return indent_decorator

Voici la sortie du journal

2018-12-31 08:14:25.536 [ INFO    ] test.py: begin my_func
2018-12-31 08:14:25.536 [ INFO    ] ---- Look, a message!
2018-12-31 08:14:25.536 [ INFO    ] test.py: end my_func

Je ne sais pas dans quelle mesure nous pouvons compter sur les code rester le même dans les versions futures de python, mais cela fonctionne pour moi dans la version 3.6.5

Je pense qu'il faudrait le simplifier davantage afin de ne pas avoir à mettre des parens sur le décorateur, donc cela pourrait être une modification ultérieure.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X