如何无需修改源码用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
相关产品推荐
相关产品推荐

