You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需修改代码:Python函数调用栈、参数及返回值追踪方案咨询

Python运行时函数调用无侵入追踪方案

核心思路

利用Python内置的sys.settrace()钩子机制,在程序启动时注入外部追踪逻辑,无需修改目标代码即可捕获所有函数的调用、返回事件,收集调用栈、参数、返回值等信息并写入日志文件。

实现代码

创建trace_logger.py文件,内容如下:

import sys
import logging
import inspect

# 配置日志输出到文件
logging.basicConfig(
    filename='function_trace.log',
    level=logging.INFO,
    format='%(asctime)s - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)

def trace_calls(frame, event, arg):
    # 仅处理函数调用和返回事件
    if event not in ('call', 'return'):
        return trace_calls

    func_name = frame.f_code.co_name
    # 跳过内置函数、匿名函数等系统级调用
    if func_name.startswith('<'):
        return trace_calls

    # 构建当前调用栈(从顶层到当前函数)
    stack = []
    current_frame = frame
    while current_frame:
        stack.append(f"{current_frame.f_code.co_name} ({current_frame.f_code.co_filename}:{current_frame.f_lineno})")
        current_frame = current_frame.f_back
    stack_str = " -> ".join(reversed(stack))

    if event == 'call':
        # 解析函数参数
        argspec = inspect.getfullargspec(frame.f_code)
        args_list = []
        # 收集位置参数
        for arg_name in argspec.args:
            args_list.append(f"{arg_name}={repr(frame.f_locals.get(arg_name))}")
        # 收集可变参数*args
        if argspec.varargs:
            args_list.append(f"*{repr(frame.f_locals.get(argspec.varargs, ()))}")
        # 收集关键字参数**kwargs
        if argspec.varkw:
            args_list.append(f"**{repr(frame.f_locals.get(argspec.varkw, {}))}")
        args_str = ", ".join(args_list)
        logging.info(f"CALL: {func_name}({args_str}) | CALL STACK: {stack_str}")
    elif event == 'return':
        logging.info(f"RETURN: {func_name} -> {repr(arg)} | CALL STACK: {stack_str}")

    return trace_calls

def main():
    if len(sys.argv) < 2:
        print("用法: python trace_logger.py <目标脚本路径> [脚本参数...]")
        sys.exit(1)
    # 调整命令行参数,让目标脚本接收自身参数
    script_path = sys.argv[1]
    sys.argv = sys.argv[1:]
    # 启动追踪
    sys.settrace(trace_calls)
    # 执行目标脚本
    with open(script_path, 'r') as f:
        code = compile(f.read(), script_path, 'exec')
        exec(code, globals(), locals())

if __name__ == '__main__':
    main()

使用方法

  1. 将上述代码保存为trace_logger.py
  2. 在命令行中运行目标脚本,通过追踪器启动:
    python trace_logger.py your_target_script.py
    
    如果目标脚本需要传入参数,直接追加在后面即可:
    python trace_logger.py your_target_script.py arg1 arg2
    

注意事项

  • 性能开销:运行时追踪会降低程序执行速度,对于性能敏感场景,可在trace_calls中添加过滤逻辑(比如仅追踪指定目录下的代码)
  • 内置函数限制:该方案无法追踪Python内置函数(如print、len),若需追踪需额外封装处理
  • 对象序列化:使用repr()序列化参数和返回值,自定义对象建议实现__repr__方法以获得清晰的日志输出
  • 递归处理:递归函数的每一层调用都会被完整记录,日志会包含递归栈的所有层级

内容的提问来源于stack exchange,提问作者Yair M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 03:57:06