如何配置cProfile在收到终止信号时保存已收集的性能分析数据?
如何让cProfile在中途终止时保存性能分析数据
这个问题很典型——当你需要分析长时间运行的函数,又没法等它跑完时,确实得让cProfile能在中途终止时保存已收集的数据。先看看你原来的代码问题:因为exit()直接终止了程序,pr.dump_stats()那一行根本没机会执行,所以没生成统计文件。下面给你一个可行的解决方案:
核心思路
通过信号处理捕获终止信号(比如Ctrl+C、系统终止指令),同时捕获exit()抛出的SystemExit异常,在退出前触发性能数据的保存操作。
修改后的代码示例
import cProfile import pstats import time import signal import sys # 全局变量保存profile对象,让信号处理函数能访问到它 profile = None def save_profile_data(signum, frame): """收到终止信号时保存profile数据""" global profile if profile is not None: profile.dump_stats('my_data.dat') print("✅ 已保存性能分析数据到my_data.dat") sys.exit(0) def foo(n): time.sleep(2) res = 0 # 模拟中途退出(比如业务逻辑里的exit调用) # exit() # 模拟长时间运行的计算任务 for i in range(10000000): res = res * 1024 + res if __name__ == "__main__": # 注册信号处理:捕获Ctrl+C(SIGINT)和系统终止信号(SIGTERM) signal.signal(signal.SIGINT, save_profile_data) signal.signal(signal.SIGTERM, save_profile_data) # 初始化并启动性能分析 profile = cProfile.Profile() profile.enable() try: foo(n=1) except SystemExit: # 捕获函数内部exit()抛出的异常,保存数据后退出 save_profile_data(None, None) finally: # 正常结束时也禁用分析并保存数据 profile.disable() profile.dump_stats('my_data.dat') # 生成可读的性能报告(可选) with open("profile_report.txt", "w") as f: stats = pstats.Stats("my_data.dat", stream=f) stats.sort_stats(pstats.SORT_TIME) # 按运行时间排序 stats.print_stats()
关键细节说明
- 信号处理:我们监听了
SIGINT(用户按Ctrl+C触发)和SIGTERM(系统发送的终止信号),收到信号时立即保存数据并安全退出。 - 捕获SystemExit:函数内部调用
exit()会抛出SystemExit异常,我们在try/except块中捕获它,确保在退出前执行数据保存。 - 全局变量的作用:信号处理函数属于异步触发,需要能访问到已初始化的Profile对象,全局变量是简单场景下的便捷方案(如果是复杂项目,也可以用类封装来避免全局变量)。
- 正常流程处理:
finally块保证函数正常执行完毕时,也会保存数据并禁用分析器,兼顾两种场景。
验证方法
- 运行代码后,按Ctrl+C终止程序,会看到控制台输出“已保存性能分析数据到my_data.dat”。
- 或者在
foo函数中取消exit()的注释,运行后程序会自动保存数据再退出。 - 打开
profile_report.txt就能看到已收集到的性能统计结果。
内容的提问来源于stack exchange,提问作者MyCoolAwsomeName
相关产品推荐
相关产品推荐

