python 转储所有活动线程的堆栈跟踪

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1032813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 21:19:31  来源:igfitidea点击:

Dump stacktraces of all active Threads

pythonmultithreadingplonezope

提问by Chriss

I'm trying to dump a list of all active threads including the current stack of each. I can get a list of all threads using threading.enumerate(), but i can't figure out a way to get to the stack from there.

我正在尝试转储所有活动线程的列表,包括每个线程的当前堆栈。我可以使用 threading.enumerate() 获取所有线程的列表,但我无法找到从那里进入堆栈的方法。

Background: A Zope/Plone app freaks out from time to time, consuming 100% of cpu and needs to be restarted. I have a feeling it's a loop which doesn't terminate properly, but i cannot reproduce it in the test-environemt for verification. I managed to register a signal handler which can be triggered from the outside, so i can trigger some code as soon as the situation occurs again. If I could dump the stacktrace for all active threads, that would give me a clue what goes wrong. The hole thing runs on python 2.4...

背景:Zope/Plone 应用程序时不时出现异常,消耗 100% 的 CPU 并需要重新启动。我有一种感觉,这是一个无法正常终止的循环,但我无法在测试环境中重现它以进行验证。我设法注册了一个可以从外部触发的信号处理程序,因此一旦这种情况再次发生,我就可以触发一些代码。如果我可以转储所有活动线程的堆栈跟踪,那会给我一个线索是什么地方出了问题。洞的东西在python 2.4上运行......

Any ideas on how to trace down situations like these are appreciated :)

任何关于如何追踪此类情况的想法都值得赞赏:)

Cheers, Chriss

干杯,克里斯

采纳答案by Martijn Pieters

When using Zope, you want to install Products.signalstackor mr.freeze; these were designed for just this purpose!

使用Zope时,要安装Products.signalstackmr.freeze;这些就是为此目的而设计的!

Send a USR1 signal to your Zope server and it'll immediately dump stack traces for all threads to the console. It'll do this even if all Zope threads are locked up.

向您的 Zope 服务器发送一个 USR1 信号,它会立即将所有线程的堆栈跟踪转储到控制台。即使所有 Zope 线程都被锁定,它也会这样做。

Under the hood these packages indirectly use threadframes; for Python versions 2.5 and up, when notusing Zope, you can build the same functionality using the sys._current_frames()function to access per-thread stack frames.

在引擎盖下,这些包间接使用threadframes; 对于 Python 2.5 及更高版本,当使用 Zope 时,您可以使用该sys._current_frames()函数构建相同的功能来访问每线程堆栈帧。

As of Zope 2.12.5this functionality is integrated into Zope itself, and there is no need to install additional packages anymore.

Zope 2.12.5 开始,此功能已集成到 Zope 本身中,不再需要安装其他软件包。

回答by codeasone

As jitter points out in an earlier answer sys._current_frames()gives you what you need for v2.5+. For the lazy the following code snippet worked for me and may help you:

正如 jitter 在之前的回答中指出的那样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"

回答by nlevitt

For Python 3.3 and later, there is faulthandler.dump_traceback().

对于 Python 3.3 及更高版本,有faulthandler.dump_traceback().

The code below produces similar output, but includes the thread name and could be enhanced to print more information.

下面的代码产生类似的输出,但包括线程名称并且可以增强以打印更多信息。

for th in threading.enumerate():
    print(th)
    traceback.print_stack(sys._current_frames()[th.ident])
    print()

回答by jitter

2.4. Too bad. From Python 2.5 on there is sys._current_frames().

2.4. 太糟糕了。从 Python 2.5 开始,有sys._current_frames().

But you could try threadframe. And if the makefile gives you trouble you could try this setup.py for threadframe

但是你可以试试threadframe。如果 makefile 给你带来麻烦,你可以试试这个setup.py for threadframe

Sample output when using threadframe

使用线程框架时的示例输出

回答by gforcada

Just for completeness sake, Products.LongRequestLoggeris super helpful to identify bottlenecks, and to do so it dumps stacktraces at specific intervals.

只是为了完整起见,Products.LongRequestLogger对识别瓶颈非常有帮助,为此它会在特定时间间隔转储堆栈跟踪。

回答by jwoolard

There is an applicable recipe on ASPN. You can use threading.enumerate()to get all the tids, then just call _async_raise() with some suitable exception to force a stack trace.

ASPN上有一个适用的配方。您可以使用threading.enumerate()来获取所有 tid,然后只需使用一些合适的异常调用 _async_raise() 即可强制进行堆栈跟踪。