Python中如何记录完整模块路径、类与函数名称?
如何在Python日志中记录完整的模块路径、类及函数名称
要实现你想要的日志输出格式(包含模块、类、函数的完整路径),默认的日志格式占位符(比如%(module)s、%(funcName)s)没法直接满足需求——因为没有内置的类名字段。不过我们可以通过自定义日志格式器结合inspect模块来自动获取这些信息,不需要修改业务代码里的日志调用逻辑。
完整解决方案代码
import logging import inspect class CustomFormatter(logging.Formatter): def format(self, record): # 遍历调用栈,找到日志调用所在的上下文(跳过logging自身的帧) frame = inspect.currentframe() try: while frame: code_frame = frame.f_code # 检查当前帧是否属于类实例方法(有self变量) if "self" in frame.f_locals: record.classname = frame.f_locals["self"].__class__.__name__ break # 检查是否属于类方法(有cls变量) elif "cls" in frame.f_locals: record.classname = frame.f_locals["cls"].__name__ break # 向上移动到上一帧 frame = frame.f_back finally: # 手动删除引用,避免循环引用导致内存泄漏 del frame # 拼接完整路径:模块名.类名.函数名(如果没有类名则只保留模块.函数) if hasattr(record, "classname"): record.full_qualname = f"{record.module}.{record.classname}.{record.funcName}" else: record.full_qualname = f"{record.module}.{record.funcName}" # 调用父类的format方法完成最终格式化 return super().format(record) # 配置日志系统 logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) # 创建控制台处理器并绑定自定义格式器 console_handler = logging.StreamHandler() formatter = CustomFormatter("%(levelname)s | %(full_qualname)s | %(message)s") console_handler.setFormatter(formatter) logger.addHandler(console_handler) # 测试代码 class MyClass: def my_function(self): logger.debug('msg') @classmethod def my_class_method(cls): logger.debug('class method msg') if __name__ == "__main__": obj = MyClass() obj.my_function() MyClass.my_class_method()
代码说明
- 自定义Formatter:重写
format方法,通过inspect.currentframe()遍历调用栈,找到包含self(实例方法)或cls(类方法)的帧,从而提取类名。 - 拼接完整路径:将模块名(
record.module)、类名、函数名(record.funcName)拼接成full_qualname字段,供格式字符串使用。 - 避免内存泄漏:遍历完成后手动删除帧引用,防止循环引用导致的内存问题。
输出效果
运行上述代码后,会得到如下输出:
DEBUG | my_module.MyClass.my_function | msg DEBUG | my_module.MyClass.my_class_method | class method msg
(注:如果你的模块在my_package下,输出会自动变成my_package.my_module.MyClass.my_function,因为record.module会自动识别当前模块的名称)
内容的提问来源于stack exchange,提问作者Tobias Uhmann




