我正在尝试转储所有活动线程的列表,包括每个线程的当前堆栈。我可以使用threading.enumerate()获取所有线程的列表,但我无法找到从那里到达堆栈的方法。
背景:Zope / Plone应用程序时不时会消失,消耗100%的cpu并需要重新启动。我感觉这是一个没有正确终止的循环,但我无法在test-environemt中重现它以进行验证。我设法注册一个可以从外部触发的信号处理程序,所以我可以在情况再次发生时立即触发一些代码。如果我可以为所有活动线程转储堆栈跟踪,这将给我一个问题的线索。洞的东西在python 2.4上运行......
有关如何追查这些情况的任何想法都值得赞赏:)
干杯, CHRISS
答案 0 :(得分:39)
正如早期回答中的抖动指出sys._current_frames()
为您提供了v2.5 +所需的内容。对于懒惰,以下代码片段对我有用,可能会对您有所帮助:
print >> sys.stderr, "\n*** STACKTRACE - START ***\n"
code = []
for threadId, stack in sys._current_frames().items():
code.append("\n# ThreadID: %s" % threadId)
for filename, lineno, name, line in traceback.extract_stack(stack):
code.append('File: "%s", line %d, in %s' % (filename,
lineno, name))
if line:
code.append(" %s" % (line.strip()))
for line in code:
print >> sys.stderr, line
print >> sys.stderr, "\n*** STACKTRACE - END ***\n"
答案 1 :(得分:19)
对于Python 3.3及更高版本,有faulthandler.dump_traceback()
。
下面的代码产生类似的输出,但包括线程名称,可以增强以打印更多信息。
for th in threading.enumerate():
print(th)
traceback.print_stack(sys._current_frames()[th.ident])
print()
答案 2 :(得分:10)
使用Zope时,您要安装Products.signalstack
或mr.freeze;这些只是为了这个目的而设计的!
向您的Zope服务器发送USR1信号,它会立即将所有线程的堆栈跟踪转储到控制台。即使所有Zope线程都被锁定,它也会这样做。
这些包间接使用threadframes
;对于Python 2.5及更高版本,当不使用Zope时,您可以使用sys._current_frames()
函数构建相同的功能来访问每个线程的堆栈帧。
从Zope 2.12.5开始,此功能已集成到Zope本身,无需再安装其他软件包。
答案 3 :(得分:7)
2.4。太糟糕了。从Python 2.5开始,有sys._current_frames()
。
但你可以试试threadframe。如果makefile给你带来麻烦,你可以尝试这个setup.py for threadframe
答案 4 :(得分:1)
为了完整起见,Products.LongRequestLogger对于识别瓶颈非常有帮助,并且这样做会以特定的时间间隔转储堆栈跟踪。
答案 5 :(得分:0)
ASPN上有适用的食谱。您可以使用threading.enumerate()
获取所有tid,然后使用一些合适的异常调用_async_raise()来强制执行堆栈跟踪。