Python中无需手动装饰函数,能否记录程序的变量与参数?
Python无需手动装饰函数实现参数与变量记录的方法
可以实现,利用Python内置的sys.settrace()全局追踪机制,就能自动捕获目标函数的调用参数和局部变量,完全不需要手动给函数加装饰器。
实现代码
import sys import inspect def trace_calls(frame, event, arg): func_name = frame.f_code.co_name # 仅追踪目标函数(可根据需求调整过滤规则) if func_name not in ['get_a', 'get_b']: return trace_calls if event == 'call': # 获取函数参数及对应值 argspec = inspect.getfullargspec(frame.f_code) param_list = [] for arg_name in argspec.args: param_list.append(f"{repr(arg_name)} = {repr(frame.f_locals.get(arg_name))}") print(f"function {func_name}:") if param_list: print(f"parameters: {', '.join(param_list)}") elif event == 'return': # 获取函数内定义的局部变量(排除参数避免重复记录) argspec = inspect.getfullargspec(frame.f_code) param_names = set(argspec.args) local_var_list = [] for var_name, var_val in frame.f_locals.items(): if var_name not in param_names: local_var_list.append(f"{repr(var_name)} = {repr(var_val)}") if local_var_list: print(f"variables: {', '.join(local_var_list)}") print() return trace_calls # 原业务代码无需修改 def get_b(a): b = 3 return b def get_a(): a = 2 return a def foo(): a = get_a() b = get_b(a) return a, b if __name__ == '__main__': # 开启全局追踪 sys.settrace(trace_calls) a, b = foo() # 关闭追踪 sys.settrace(None)
运行输出
执行后会得到和你期望一致的结果:
function get_a: variables: 'a' = 2 function get_b: parameters: 'a' = 2 variables: 'b' = 3
核心逻辑说明
sys.settrace():设置全局追踪回调,程序运行时每个函数的call(调用)、return(返回)等事件都会触发该回调。- 参数捕获:在
call事件中,通过inspect.getfullargspec获取函数的参数列表,再从frame.f_locals(当前函数的局部变量字典)中取出参数值。 - 局部变量捕获:在
return事件中,过滤掉参数(避免重复记录),提取函数内部定义的变量并打印。 - 函数过滤:通过判断函数名,只追踪你关心的函数,避免输出无关函数的信息。
注意事项
- 全局追踪会带来一定性能损耗,仅适合调试场景,不要在生产环境启用。
- 如果需要处理带默认参数、
*args/**kwargs的函数,可以扩展argspec的处理逻辑,比如添加对varargs和varkw的解析。 - 对于嵌套函数、类方法等复杂场景,需要根据实际情况调整追踪逻辑。
内容的提问来源于stack exchange,提问作者David Lasry
相关产品推荐
相关产品推荐

