我需要在一段随机的时间内运行一个python脚本,暂停它,获得一个堆栈追溯,并取消暂停。我已经用Google搜索了一些方法来做到这一点,但我认为没有明显的解决方案。
答案 0 :(得分:12)
pip install statprof
(或easy_install statprof
),然后使用:
import statprof
statprof.start()
try:
my_questionable_function()
finally:
statprof.stop()
statprof.display()
来自this blog post的模块有一些背景知识:
但为什么会这么重要? Python已经有两个内置的分析器:lsprof和长期不赞成的热门。 lsprof的问题在于它只跟踪函数调用。如果你在一个函数中有一些热循环,lsprof几乎一文不值,无法确定哪些是真正重要的。
几天前,我发现自己正处于lsprof失败的状态:它告诉我我有一个热门功能,但功能对我来说并不熟悉,而且很长时间以后它并不是很明显问题是。
在Twitter和Google+上做了一些乞讨之后,有人指着我做了一个statprof。但是有一个问题:虽然它正在进行统计抽样(耶!),它只是在采样时跟踪函数的第一行(wtf!?)。所以我解决了这个问题,提炼了文档,现在它既可用又不误导。以下是其输出示例,更准确地定位该热函数中的违规行:
% cumulative self time seconds seconds name 68.75 0.14 0.14 scmutil.py:546:revrange 6.25 0.01 0.01 cmdutil.py:1006:walkchangerevs 6.25 0.01 0.01 revlog.py:241:__init__ [...blah blah blah...] 0.00 0.01 0.00 util.py:237:__get__ --- Sample count: 16 Total time: 0.200000 seconds
我已经将statprof上传到Python包索引,因此安装起来几乎是微不足道的:“easy_install statprof”并且你已经启动并运行了。
自the code is up on github以来,欢迎提供错误报告和改进。享受!
答案 1 :(得分:5)
我可以想到几个几种方法来做到这一点:
不是在程序运行时尝试获取堆栈跟踪,而是在其上触发一个中断,并解析输出。您可以使用shell脚本或另一个调用您的应用程序作为子进程的python脚本来执行此操作。在this answer to a C++-specific question中解释了基本思想,并进行了相当彻底的辩护。
sys.excepthook
),而不必解析输出。不幸的是,Python没有任何方法可以从发生异常的地方继续,因此您无法在记录后继续执行。为了从正在运行的程序中实际获取堆栈跟踪, 可能必须破解实现。因此,如果您真的想这样做,可能值得花时间查看pypy,这是一个主要用Python编写的Python实现。我不知道在pypy中这样做会有多方便。我猜它不会特别方便,因为它会涉及到基本上每个指令都引入一个钩子,我认为这是非常低效的。另外,我认为除了需要很长时间才能达到你想要开始堆栈跟踪的状态之外,第一个选项没有多大优势。
gdb
调试器存在set of macros,旨在方便调试Python本身。 gdb可以附加到一个外部进程(在这种情况下是执行你的应用程序的python实例),并且几乎可以用它做任何事情。似乎宏pystack
将在当前执行点为您提供Python堆栈的回溯。我认为自动执行此过程非常简单,因为您可以(最坏的情况下)使用gdb
或其他任何方式将文本提供到expect
。
答案 2 :(得分:3)
Python已经包含了执行所描述内容所需的一切,无需破解解释器。
您只需将traceback
模块与sys._current_frames()
功能结合使用即可。您所需要的只是一种以您想要的频率转储所需回溯的方法,例如使用UNIX信号或其他线程。
要快速启动代码,您可以完全按照this commit:
执行的操作从该提交复制threads.py
模块,或者至少复制堆栈跟踪转储功能(ZPL许可证,非常宽松):
将其连接到信号处理程序,例如SIGUSR1
然后你只需要运行你的代码并根据需要随时使用SIGUSR1“杀死”它。
对于使用相同技术不时“采样”单个线程的单个函数的情况,使用另一个线程进行计时,我建议解析Products.LongRequestLogger的代码及其测试(由真的,在Nexedi)的雇佣下:
这是否是正确的“统计”分析,answer引用的Mike Dunlavey intuited提出了一个令人信服的论据,即这是一种非常强大的“性能调试”技术,并且我有个人经验,它确实有助于快速放大性能问题的真正原因。
答案 3 :(得分:2)
要为Python实现外部统计分析器,您将需要一些通用调试工具来让您查询另一个进程,以及一些Python特定工具来获取解释器状态。
这一般不是一个简单的问题,但您可能想尝试从GDB 7和相关的CPython分析工具开始。
答案 4 :(得分:1)
有一个用C编写的跨平台采样(统计)Python分析器,名为vmprof-python。 由PyPy团队成员开发,它支持PyPy和CPython。 它适用于Linux,Mac OSX和Windows。它用C语言编写,因此开销非常小。 它描述了Python代码以及从Python代码生成的本机调用。 此外,除了函数名称之外,它还有一个非常有用的选项来收集有关函数内部执行行的统计信息。 它还可以分析内存使用情况(通过跟踪堆大小)。
可以通过API或控制台从Python代码调用它。 有一个Web UI可以查看配置文件转储:vmprof.com,也是open sourced。
此外,一些Python IDE(例如PyCharm)与它集成,允许运行探查器并在编辑器中查看结果。
答案 5 :(得分:1)
问了问题七年后,现在有几种适用于Python的良好统计分析器。除了Dmitry Trofimov在this答案中已经提到的vmprof之外,还有vprof和pyflame。它们全都以一种或另一种方式支持flame graphs,使您可以很好地了解花费的时间。
答案 6 :(得分:1)
Austin是用于CPython的帧堆栈采样器,可用于为不需要工具的Python制作统计分析器,并引入最小的开销。最简单的方法是将Flame的Austin输出传递给管道。但是,您可以使用自定义应用程序获取Austin的输出,以制作完全适合您需求的自己的探查器。
这是Austin TUI的屏幕截图,Austin TUI是一个终端应用程序,它提供了运行中的Python应用程序中正在发生的一切的俯视图。
这是Web Austin,这是一个Web应用程序,向您显示所收集样品的实时火焰图。您可以配置服务应用程序的地址,然后允许您进行远程分析。
答案 7 :(得分:0)
对于Python,有py-spy转储堆栈跟踪。可以通过speedscope
对转储进行分析来源:Guidelines