Python如何在函数内获取调用自身的代码行源码
Python函数内获取调用行、提取赋值变量名实现方案
核心逻辑是通过上层调用栈帧自带的行号信息,直接定位源码文件的对应调用行,天然适配同一函数在模块内被多次调用的场景,不需要处理全量源码的行号偏移问题。
完整可运行示例
import sys def fct1(): # 获取直接调用当前函数的上层栈帧,参数1代表向上找1层 caller_frame = sys._getframe(1) # 从栈帧中提取调用发生的精确行号、调用方所在源码文件路径 call_line_num = caller_frame.f_lineno caller_file_path = caller_frame.f_code.co_filename # 读取源码文件,定位到对应行拿到调用语句 call_line = "" with open(caller_file_path, "r", encoding="utf-8") as f: for current_line_num, line_content in enumerate(f, start=1): if current_line_num == call_line_num: call_line = line_content.strip() break # 提取赋值给返回值的变量名 if "=" in call_line: target_var_name = call_line.split("=")[0].strip() # 示例返回带name属性的对象,可根据自己的业务逻辑调整 class Result: def __init__(self, name): self.name = name return Result(target_var_name) # 处理无赋值直接调用的边界场景 return None # 测试多次调用场景 a = fct1() b = fct1() print(a.name) # 输出: a print(b.name) # 输出: b
适配注意事项
- 方案依赖运行时能读取到对应
.py源码文件,在交互式REPL环境、打包为无源码二进制的场景下会失效,常规脚本运行、模块导入调用的生产场景均可正常使用。 - 如果遇到调用语句跨行书写的场景(比如赋值换行、函数参数拆成多行),可以在定位到起始调用行后,向后连续读取若干行拼接为完整语句,再做变量名提取即可覆盖复杂写法。
sys._getframe()的入参代表向上查找栈帧的层数:如果fct1外层还有装饰器、包装函数,需要对应调大入参值,确保拿到真正发起业务调用的那一层栈帧。- 不建议使用
inspect.getsource(sys._getframe().f_back)获取全量上层源码后手动算行号,这种方式遇到装饰器、代码注释空行偏移时很容易定位错位,稳定性远低于直接用栈帧自带的行号读文件。
内容的提问来源于stack exchange,提问作者u2gilles
相关产品推荐
相关产品推荐

