如何在父类方法中获取调用者的真实行号?
解决父类中获取真实调用者行号的问题
问题分析
你当前代码里用stack()[1]拿到的是直接调用父类info方法的栈帧——也就是子类Child中super().info(message)所在的行。当子类重写方法并转发调用到父类时,父类默认只能捕获到子类内部的调用行,而非业务代码中实际调用child.info()的行号。
解决方案
核心思路是遍历调用栈,跳过所有属于当前类(及子类)的方法调用,定位到第一个外部业务代码的调用栈帧。可以实现一个通用辅助函数来处理这个逻辑:
from inspect import getframeinfo, stack def get_caller_frame(): frames = stack() # 遍历栈帧,跳过Parent和Child类的内部调用 for frame_info in frames: frame = frame_info[0] # 获取当前栈帧所属的类名(如果是类方法调用) class_name = frame.f_locals.get('self', None).__class__.__name__ if 'self' in frame.f_locals else None if class_name in ('Parent', 'Child'): continue # 找到第一个外部调用的栈帧后返回 return frame # 兜底返回最后一个栈帧(极端情况备用) return frames[-1][0] class Parent(): def __init__(self): pass def info(self, message): caller = getframeinfo(get_caller_frame()) print(caller.lineno) class Child(Parent): def __init__(self): super().__init__() def info(self, message): super().info(message) # 测试 child = Child() child.info("test line") # 现在会输出这一行的行号(比如第32行就输出32) parent = Parent() parent.info("test parent") # 父类实例调用依然正常返回正确行号
针对AWS Lambda PowerTools日志库的适配
如果你是重写PowerTools的Logger类,逻辑完全通用:只需在日志记录的核心方法中,过滤掉日志类自身的调用栈帧,定位到业务代码的实际调用点。示例如下:
from inspect import getframeinfo, stack from aws_lambda_powertools import Logger class CustomLogger(Logger): def _get_caller_info(self): frames = stack() # 跳过日志类自身的调用(包括CustomLogger和父类Logger) target_classes = (self.__class__.__name__, Logger.__name__) for frame_info in frames: frame = frame_info[0] class_name = frame.f_locals.get('self', None).__class__.__name__ if 'self' in frame.f_locals else None if class_name in target_classes: continue caller = getframeinfo(frame) return caller.lineno, caller.filename # 兜底使用父类原有逻辑 return super()._get_caller_info() # 使用示例 logger = CustomLogger(service="my-service") def lambda_handler(event, context): logger.info("Hello from Lambda") # 日志会记录这一行的行号,而非CustomLogger内部调用行 return {"message": "ok"}
内容的提问来源于stack exchange,提问作者Tamil selvan
相关产品推荐
相关产品推荐

