我've another script that does the same thing, except it communicates with the running process through a pipe (to allow for debugging backgrounded processes etc). Its a bit large to post here, but I'已将其添加为python cookbook recipe .
import sys, traceback, signal
import threading
import os
def dumpstacks(signal, frame):
id2name = dict((th.ident, th.name) for th in threading.enumerate())
for threadId, stack in sys._current_frames().items():
print(id2name[threadId])
traceback.print_stack(f=stack)
signal.signal(signal.SIGQUIT, dumpstacks)
os.killpg(os.getpgid(0), signal.SIGQUIT)
24 回答
我不知道类似于java's response to SIGQUIT的任何内容,因此您可能需要将其构建到您的应用程序中 . 也许你可以在另一个线程中创建一个服务器,可以在响应某种消息时获得堆栈跟踪?
使用检查模块 .
stack(context = 1)返回调用者帧上方的堆栈记录列表 .
我发现它确实非常有用 .
获得一个没有准备的python程序的堆栈跟踪,在没有调试符号的股票python中运行可以使用pyrasite来完成 . 在Ubuntu Trusty上像我一样的魅力:
(帽子提示@Albert,其答案中包含指向此的工具,以及其他工具 . )
看一下_36435_模块,Python 3.3中的新模块 . PyPI上提供了用于Python 2的faulthandler backport .
安装信号处理程序的建议很好,我经常使用它 . 例如,bzr默认情况下安装一个SIGQUIT处理程序,该处理程序调用
pdb.set_trace()
以立即将您放入pdb提示符 . (有关详细信息,请参阅bzrlib.breakin模块的源代码 . )使用pdb,您不仅可以获取当前堆栈跟踪,还可以检查变量等 .但是,有时我需要调试一个我没有远见来安装信号处理程序的进程 . 在linux上,你可以将gdb附加到进程并获得带有一些gdb宏的python堆栈跟踪 . 把http://svn.python.org/projects/python/trunk/Misc/gdbinit放在
~/.gdbinit
中,然后:附加gdb:
gdb -p
PID
获取python堆栈跟踪:
pystack
不幸的是,这并不完全可靠,但它大部分时间都有效 .
最后,附加
strace
通常可以让您了解流程正在做什么 .您也可以很好地格式化堆栈跟踪,请参阅docs .
Edit :为了模拟Java的行为,正如@Douglas Leeder所建议的那样,添加:
到应用程序中的启动代码 . 然后,您可以通过将
SIGUSR1
发送到正在运行的Python进程来打印堆栈 .traceback模块有一些很好的功能,其中包括:print_stack:
我有这样的情况下使用的模块 - 一个进程将运行很长一段时间,但有时会因未知和不可复制的原因而卡住 . 它有点hacky,只适用于unix(需要信号):
要使用,只需在程序启动时调用listen()函数(你甚至可以将它粘贴在site.py中让所有python程序都使用它),并让它运行 . 在任何时候,使用kill或python发送进程SIGUSR1信号:
这将导致程序在当前所处的位置中断到python控制台,向您显示堆栈跟踪,并让您操作变量 . 使用control-d(EOF)继续运行(但请注意,您可能会在发出信号的位置中断任何I / O等,因此它不是完全非侵入式的 .
我've another script that does the same thing, except it communicates with the running process through a pipe (to allow for debugging backgrounded processes etc). Its a bit large to post here, but I'已将其添加为python cookbook recipe .
我会将此作为评论添加到haridsv's response,但我缺乏这样做的声誉:
我们中的一些人仍然坚持使用早于2.6的Python版本(Thread.ident需要),所以我在Python 2.5中使用了代码(尽管没有显示线程名称):
你可以试试faulthandler module . 使用
pip install faulthandler
安装并添加:在你的程序的开头 . 然后将SIGUSR1发送到您的进程(例如:
kill -USR1 42
),以显示标准输出的所有线程的Python回溯 . Read the documentation了解更多选项(例如:登录文件)以及其他显示回溯的方法 .该模块现在是Python 3.3的一部分 . 对于Python 2,请参阅http://faulthandler.readthedocs.org/
我在使用python扩展的GDB阵营 . 按照https://wiki.python.org/moin/DebuggingWithGdb,这意味着
dnf install gdb python-debuginfo
或sudo apt-get install gdb python2.7-dbg
gdb python <pid of running process>
py-bt
还要考虑
info threads
和thread apply all py-bt
.如果您需要使用uWSGI执行此操作,则内置Python Tracebacker并且只需在配置中启用它(数字附加到每个工作者的名称):
完成此操作后,只需连接到套接字即可打印回溯:
在Solaris上,您可以使用pstack(1)不需要更改python代码 . 例如 .
我将一些附加到正在运行的Python进程中的工具一起攻击并注入一些代码来获取Python shell .
看这里:https://github.com/albertz/pydbattach
您可以使用带有curses接口的Python调试器PuDB来执行此操作 . 只需添加
到您的代码并在想要破解时使用Ctrl-C . 你可以继续使用
c
并在你错过它时多次再次中断并想再试一次 .如果您使用的是Linux系统,请使用
gdb
与Python调试扩展的强大功能(可以在python-dbg
或python-debuginfo
包中) . 它还有助于多线程应用程序,GUI应用程序和C模块 .运行程序:
这指示
gdb
准备python <programname>.py <arguments>
和r
un it .现在程序挂起时,切换到
gdb
控制台,按Ctr C并执行:见example session以及更多信息here和here .
pyringe是一个调试器,可以在不进行任何先验设置的情况下与正在运行的python进程,打印堆栈跟踪,变量等进行交互 .
虽然我经常使用在过去的信号处理程序解决方案中,在某些环境中仍然可能经常难以重现该问题 .
我几乎总是处理多个线程,主线程通常没有做太多,所以最有趣的是转储所有堆栈(这更像是Java的转储) . 这是基于this blog的实现:
python -dv yourscript.py
这将使解释器以调试模式运行,并为您提供解释器正在执行的操作的跟踪 .
如果您想以交互方式调试代码,您应该像这样运行它:
python -m pdb yourscript.py
这告诉python解释器用模块“pdb”运行你的脚本,这是python调试器,如果你运行它就像解释器将以交互模式执行,就像GDB一样
我正在寻找一段时间来调试我的线程,我在这里找到了感谢haridsv . 我使用traceback.print_stack()使用稍微简化的版本:
为了我的需要,我也按名称过滤线程 .
没有办法挂钩到正在运行的python进程并获得合理的结果 . 如果进程锁定,我所做的就是挂钩并试图找出究竟发生了什么 .
不幸的是,通常strace是“修复”竞争条件的观察者,因此那里的输出也是无用的 .
这里真正帮助我的是spiv's tip(我会投票并评论我是否有声望点)从一个毫无准备的Python进程中获取堆栈跟踪 . 除非直到我modified the gdbinit script才行 . 所以:
下载http://svn.python.org/projects/python/trunk/Misc/gdbinit并将其放入
~/.gdbinit
编辑它,将PyEval_EvalFrame更改为PyEval_EvalFrameEx [编辑:不再需要;截至2010-01-14,链接文件已经有此更改]
附加gdb:
gdb -p PID
获取python堆栈跟踪:
pystack
值得一看Pydb,"an expanded version of the Python debugger loosely based on the gdb command set" . 它包括信号管理器,它可以在发送指定信号时负责启动调试器 .
2006年夏季代码项目考虑在名为mpdb的模块中向pydb添加远程调试功能 .
在Python 3中,pdb将在您第一次在调试器中使用c(ont(inue))时自动安装信号处理程序 . 之后按下Control-C会让你回到那里 . 在Python 2中,这是一个单行程,即使在相对较旧的版本中也应该可以工作(在2.7中测试但是我将Python源代码检查回2.4并且看起来没问题):
如果你花费任何时间调试Python,pdb是值得学习的 . 界面有点迟钝,但对于使用过类似工具的人来说应该很熟悉,例如gdb .