Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何让logging decorator记录它所在的文件名';是否使用了,而不是定义在何处?_Python_Logging - Fatal编程技术网

Python 如何让logging decorator记录它所在的文件名';是否使用了,而不是定义在何处?

Python 如何让logging decorator记录它所在的文件名';是否使用了,而不是定义在何处?,python,logging,Python,Logging,我使用日志记录模块和文件名格式来捕获代码的日志输出。这很好,因为现在我总是知道消息是从哪个文件发送的。但是,我有一个缩进日志装饰器,我希望实际记录使用它的文件名,而不是定义装饰器的模块。这可能吗 下面是一个简短的例子,说明它现在正在做什么: test.py 日志输出 现在,我希望所有三条消息都包含test.py如下所示: 期望输出 log.py 通过复制标准库的日志模块使用的一些代码检查,我能够自动生成文件名和开始/结束消息。我删除了手册的开始和结束消息,认为这更符合您的意图。我还从日志格式中删

我使用
日志记录
模块和
文件名
格式来捕获代码的日志输出。这很好,因为现在我总是知道消息是从哪个文件发送的。但是,我有一个缩进日志装饰器,我希望实际记录使用它的文件名,而不是定义装饰器的模块。这可能吗

下面是一个简短的例子,说明它现在正在做什么:

test.py 日志输出 现在,我希望所有三条消息都包含
test.py
如下所示:

期望输出 log.py
通过复制标准库的日志模块使用的一些代码检查,我能够自动生成文件名和开始/结束消息。我删除了手册的开始和结束消息,认为这更符合您的意图。我还从日志格式中删除了文件名,并将其添加到缩进装饰器记录的文本中

    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
这是日志输出

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
我不知道我们能在多大程度上依赖于代码在python的未来版本中保持不变,但这在3.6.5中对我很有用


我怀疑它应该进一步简化,这样您就不必在装饰器上添加paren,这样可能会在以后进行编辑。

我注意到,在c:\Python36\Lib\logging\u init\uupy.py中,它通过直接检查“findCaller”中的堆栈来获取文件名,并发现第一件不在该文件中的东西。更改日志模块本身是正确的,所以我现在被困在那里,正要睡觉。通过适配器的调用发生在log.py中,但它仍然会找到test.py。可能需要定义自己的格式变量并额外传递它。顺便说一句,我发现在调试时使用stream=sys.stdout更容易
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
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
    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
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