我有一个Python应用程序,它不时卡住,我不知道在哪里。

是否有任何方法向Python解释器发出信号,以显示正在运行的确切代码?

某种飞行中的堆叠痕迹?

相关问题:

从Python代码中的方法打印当前调用堆栈 检查正在运行的进程正在做什么:打印未检测的Python程序的堆栈跟踪


当前回答

Pyringe是一个调试器,可以与正在运行的python进程交互,打印堆栈跟踪,变量等,而不需要任何先验设置。

虽然我过去经常使用信号处理程序解决方案,但在某些环境中仍然很难重现这个问题。

其他回答

你可以使用hypno包,像这样:

hypno <pid> "import traceback; traceback.print_stack()"

这将把堆栈跟踪打印到程序的标准输出中。

或者,如果你不想打印任何东西到stdout,或者你没有访问它的权限(例如守护进程),你可以使用madbg包,这是一个python调试器,允许你附加到一个正在运行的python程序并在当前终端中调试它。它类似于pyrasite和pyringe,但更新,不需要gdb,并使用IPython作为调试器(这意味着颜色和自动补全)。

要查看正在运行的程序的堆栈跟踪,你可以运行:

madbg attach <pid>

在调试器shell中,输入: 英国电信

免责声明——这两个包都是我写的

安装信号处理程序的建议很好,我经常使用它。例如,bzr默认安装一个SIGQUIT处理程序,调用pdb.set_trace()立即将您放入pdb提示符中。(参见bzrlib。进入模块的源代码以获取确切的细节。)使用pdb,您不仅可以获得当前堆栈跟踪(使用(w)here命令),还可以检查变量等。

然而,有时我需要调试一个我没有预见到在其中安装信号处理程序的进程。在linux上,您可以将gdb附加到进程,并使用一些gdb宏获得python堆栈跟踪。将http://svn.python.org/projects/python/trunk/Misc/gdbinit放在~/中。gdbinit,然后:

附加gdb: gdb -p PID 获取python堆栈跟踪:pystack

不幸的是,它不是完全可靠的,但它在大多数时候都是有效的。参见https://wiki.python.org/moin/DebuggingWithGdb

最后,附加strace通常可以让您很好地了解进程正在做什么。

如果您使用的是Linux系统,请使用出色的gdb和Python调试扩展(可以在Python -dbg或Python -debuginfo包中)。它还有助于多线程应用程序、GUI应用程序和C模块。

使用以下命令运行程序:

$ gdb -ex r --args python <programname>.py [arguments]

这指示gdb准备python <programname>.py <arguments>并运行它。

现在当你的程序挂起时,切换到gdb控制台,按Ctr+C并执行:

(gdb) thread apply all py-list

参见示例会话和更多信息在这里和这里。

我几乎总是处理多线程,主线程通常不做太多,所以最有趣的是转储所有堆栈(这更像Java的转储)。下面是一个基于这个博客的实现:

import threading, sys, traceback

def dumpstacks(signal, frame):
    id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
    code = []
    for threadId, stack in sys._current_frames().items():
        code.append("\n# Thread: %s(%d)" % (id2name.get(threadId,""), 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()))
    print("\n".join(code))

import signal
signal.signal(signal.SIGQUIT, dumpstacks)

您可以尝试faulthandler模块。使用pip Install faulthandler安装它,并添加:

import faulthandler, signal
faulthandler.register(signal.SIGUSR1)

在程序开始的时候。然后将SIGUSR1发送到进程(例如:kill -USR1 42),以显示所有线程的Python回溯到标准输出。阅读文档以获得更多选项(例如:登录到文件中)和其他显示回溯的方法。

该模块现在是Python 3.3的一部分。对于Python 2,请参见http://faulthandler.readthedocs.org/