如何在Python日志语句中包含模块的相对路径?

1yjd4xko  于 2023-11-15  发布在  Python
关注(0)|答案(3)|浏览(123)

我的项目有一个嵌套在根包下面的子包,如下所示:

  • 第一个月
  • __init__.py
  • topmodule.py
  • subpackage/
  • __init__.py
  • nested.py

我的目标是让日志记录的格式如下:

mypackage/topmodule.py:123: First log message
mypackage/subpackage/nested.py:456: Second log message

字符串
这样路径就可以在我的终端上点击了。
我尝试了以下格式。

  • '%(modulename).pys:%(lineno): %(message)s'不可点击(点需要是斜线):
mypackage.topmodule.py:123: First log message
mypackage.subpackage.nested.py:456: Second log message

  • 'mypackage/%(filename)s:%(lineno): %(message)s'不适用于子包:
mypackage/topmodule.py:123: First log message
mypackage/nested.py:456: Second log message

  • '%(pathname)s:%(lineno): %(message)s'生成可点击的路径,但它们太长了,以至于切断了我的其余日志记录:
/Users/jacebrowning/Documents/mypackage/topmodule.py:123: First log message
/Users/jacebrowning/Documents/mypackage/subpackage/nested.py:456: Second log message


是否有一个日志模式可以传递给logging.basicConfig(format='???'),以产生我想要的日志记录?

hmae6n7t

hmae6n7t1#

你必须做额外的处理来得到你想要的路径。
您可以通过创建自定义过滤器来执行此类处理并向日志记录添加其他信息,包括您自己的包的“本地”路径。
过滤器实际上并不一定要进行过滤,但它们确实可以访问所有日志记录,因此它们是更新丢失信息的记录的好方法。只需确保在完成时返回True

import logging
import os
import sys

class PackagePathFilter(logging.Filter):
    def filter(self, record):
        pathname = record.pathname
        record.relativepath = None
        abs_sys_paths = map(os.path.abspath, sys.path)
        for path in sorted(abs_sys_paths, key=len, reverse=True):  # longer paths first
            if not path.endswith(os.sep):
                path += os.sep
            if pathname.startswith(path):
                record.relativepath = os.path.relpath(pathname, path)
                break
        return True

字符串
这将在日志记录中找到pathname的父目录sys.path条目,并在日志记录中添加新的relativepath条目。然后您可以使用%(relativepath)s将其包含在日志中。
将过滤器添加到您使用自定义格式化程序配置的任何 * 处理程序 * 中:

handler.addFilter(PackagePathFilter())


'%(relativepath)s:%(lineno)s: %(message)s'一起作为格式,您的日志消息将如下所示:

mypackage/topmodule.py:123: First log message
mypackage/subpackage/nested.py:456: Second log message


(实际输出,除了我修改了行号)。

ercv8c1e

ercv8c1e2#

这会产生相同的结果。

import os
import logging

    class PackagePathFilter(logging.Filter):
        def filter(self, record):
            record.pathname = record.pathname.replace(os.getcwd(),"")
            return True

字符串
添加处理程序

handler.addFilter(PackagePathFilter())


并与'%(pathname)s:%(lineno)s: %(message)s'一起作为您的日志格式。

ccgok5k5

ccgok5k53#

可以使用Filter s,但我认为更pythonic的方法是扩展Formatter

class CustomFormatter(logging.Formatter):
    def __init__(self, root_path, fmt, datefmt=None):
        super().__init__(fmt, datefmt)
        self.root_path = root_path

    def format(self, record):
        # Replace the full pathname with the relative path
        record.pathname = os.path.relpath(record.pathname, self.root_path)
        return super().format(record)

字符串

相关问题