从正在运行的Python应用程序中显示堆栈跟踪

我有这个不时被卡住的Python应用程序,我找不到在哪里。

有什么方法可以告诉Python解释器向您显示正在运行的确切代码吗?

某种即时堆栈跟踪?

相关问题:

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

  • 我有这样的情况下使用的模块 - 一个进程将会运行很长时间,但有时会出现未知和不可重复的原因。 它有点怪异,只适用于unix(需要信号):

    import code, traceback, signal
    
    def debug(sig, frame):
        """Interrupt running process, and provide a python prompt for
        interactive debugging."""
        d={'_frame':frame}         # Allow access to frame object.
        d.update(frame.f_globals)  # Unless shadowed by global
        d.update(frame.f_locals)
    
        i = code.InteractiveConsole(d)
        message  = "Signal received : entering python shell.nTraceback:n"
        message += ''.join(traceback.format_stack(frame))
        i.interact(message)
    
    def listen():
        signal.signal(signal.SIGUSR1, debug)  # Register handler
    

    要使用,只需在程序启动时的某个时刻调用listen()函数(甚至可以将它粘贴到site.py中让所有python程序使用它),然后让它运行。 在任何时候,使用kill或python发送进程一个SIGUSR1信号:

        os.kill(pid, signal.SIGUSR1)
    

    这将导致程序在当前所处的位置断开到一个python控制台,向您显示堆栈跟踪,并让您操作这些变量。 使用control-d(EOF)继续运行(尽管请注意,您可能会在您发出信号时中断任何I / O等,因此它不是完全非侵入式的。

    我有另一个脚本执行相同的操作,除了通过管道与正在运行的进程通信(以允许调试后台进程等)。 在这里发布它有点大,但是我已经将它作为一个python食谱食谱加入。


    建议安装一个信号处理程序是一个很好的建议,我使用它很多。 例如,默认情况下,bzr会安装一个调用pdb.set_trace()立即将您放入pdb提示符的SIGQUIT处理程序。 (有关确切的细节,请参阅bzrlib.breakin模块的源代码。)使用pdb,您不仅可以获取当前堆栈跟踪,还可以检查变量等。

    但是,有时我需要调试一个我没有先见之明的进程来安装信号处理程序。在linux上,您可以将gdb附加到进程并使用某些gdb宏来获取python堆栈跟踪。 把http://svn.python.org/projects/python/trunk/Misc/gdbinit放入~/.gdbinit ,然后:

  • 附加gdb: gdb -p PID
  • 获取python堆栈跟踪: pystack
  • 不幸的是,这不是完全可靠的,但它在大多数时间都有效。

    最后,附加strace通常会给你一个好主意,一个过程在做什么。


    我几乎总是处理多个线程,主线程通常没有太多的工作,所以最有意思的是转储所有的堆栈(这更像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)
    
    链接地址: http://www.djcxy.com/p/14459.html

    上一篇: Showing the stack trace from a running Python application

    下一篇: What does JVM flag CMSClassUnloadingEnabled actually do?