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

Jac*_*ing 2 python logging

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

  • mypackage/
    • __init__.py
    • topmodule.py
    • subpackage/
      • __init__.py
      • nested.py

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

mypackage/topmodule.py:123: First log message
mypackage/subpackage/nested.py:456: Second log message
Run Code Online (Sandbox Code Playgroud)

这样路径就可以在我的终端中单击


我尝试了以下格式。

  • '%(modulename).pys:%(lineno): %(message)s' 不可点击(点必须为斜线):

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

    mypackage/topmodule.py:123: First log message
    mypackage/nested.py:456: Second log message
    
    Run Code Online (Sandbox Code Playgroud)
  • '%(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
    
    Run Code Online (Sandbox Code Playgroud)

我是否可以传递给我logging.basicConfig(format='???')所需的日志记录模式?

Mar*_*ers 5

您必须执行其他处理才能在此处获得所需的路径。

您可以通过创建自定义过滤器进行此类处理,并将其他信息添加到日志记录中,包括您自己软件包的“本地”路径。

过滤器实际上不必进行过滤,但是它们确实可以访问所有日志记录,因此,它们是用缺少的信息更新记录的好方法。只需确保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
Run Code Online (Sandbox Code Playgroud)

这将在日志记录中找到作为sys.path父目录的条目,并在日志记录中pathname添加一个新relativepath条目。然后,您可以用来%(relativepath)s将其包括在日志中。

将过滤器添加到使用自定义格式化程序配置的任何处理程序

handler.addFilter(PackagePathFilter())
Run Code Online (Sandbox Code Playgroud)

以及'%(relativepath)s:%(lineno)s: %(message)s'日志消息的格式如下:

mypackage/topmodule.py:123: First log message
mypackage/subpackage/nested.py:456: Second log message
Run Code Online (Sandbox Code Playgroud)

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