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

如何无需修改源码用Python实现对其他Python程序的执行分析?

更优实现方案

1. 使用sys.settrace跟踪函数调用

这是Python内置的进程内跟踪机制,无需跨进程通信,比pdb子进程方案高效得多,能直接Hook函数的调用与返回事件。

实现步骤:

  • 在analyzer.py中定义跟踪回调函数,该函数会在函数调用、返回、异常等事件触发时执行。
  • 回调函数中判断当前是否为目标函数func的事件:
    • 触发call事件时,记录调用次数,通过函数帧对象frame获取传入参数。
    • 触发return事件时,获取返回值并补全记录。
  • 通过python -m analyzer main.py的方式启动,让Python先加载跟踪逻辑,再执行目标程序。

核心代码示例:

import sys
import inspect

target_func = "func"
call_count = 0
call_records = []

def trace_handler(frame, event, arg):
    global call_count
    if event == "call":
        func_name = frame.f_code.co_name
        if func_name == target_func:
            call_count += 1
            # 解析函数参数
            sig = inspect.signature(frame.f_code)
            arg_values = inspect.getargvalues(frame)
            params = {name: arg_values.locals[name] for name in sig.parameters}
            call_records.append({"call_num": call_count, "args": params})
    elif event == "return" and frame.f_code.co_name == target_func:
        call_records[-1]["return_value"] = arg
    return trace_handler

def main():
    sys.settrace(trace_handler)
    # 加载并运行目标程序
    sys.argv = sys.argv[1:]
    target_module = sys.argv[0].replace(".py", "")
    __import__(target_module)

if __name__ == "__main__":
    main()

2. 动态注入监控装饰器

通过修改目标模块的函数对象,为func动态添加装饰器,无需改动源码,逻辑简洁直观。

实现步骤:

  • 在analyzer.py中定义监控装饰器,用于记录调用次数、参数和返回值。
  • 动态加载目标模块,替换模块内的func为被装饰后的函数。
  • 触发目标模块的执行逻辑。

核心代码示例:

import importlib
import sys

call_count = 0
call_records = []

def monitor_decorator(func):
    def wrapper(*args, **kwargs):
        global call_count
        call_count += 1
        call_records.append({"call_num": call_count, "args": args, "kwargs": kwargs})
        result = func(*args, **kwargs)
        call_records[-1]["return_value"] = result
        return result
    return wrapper

def main():
    target_path = sys.argv[1]
    target_module = target_path.replace(".py", "")
    # 加载目标模块
    module = importlib.import_module(target_module)
    # 替换目标函数
    if hasattr(module, "func"):
        module.func = monitor_decorator(module.func)
    # 执行目标程序逻辑
    if hasattr(module, "main"):
        module.main()
    else:
        exec(open(target_path).read(), module.__dict__)

if __name__ == "__main__":
    main()

原pdb方案的不足

  • 跨进程通信开销大,频繁序列化并打印locals()会导致性能损耗,尤其在函数高频调用场景下。
  • pdb的交互逻辑存在同步风险,命令发送时机偏差可能导致程序阻塞或监控数据丢失。

方案对比

  • sys.settrace:灵活性最高,能覆盖所有函数执行事件,性能表现较好,适合复杂监控需求。
  • 动态装饰器:代码简洁,侵入性极低(仅运行时修改函数对象),适合单一目标函数的监控场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 04:32:47