是否有任何方式向Python解释器发出信号,以向您显示正在运行的确切代码?
某种实时堆栈跟踪?
相关问题:
从Python中的方法打印当前调用堆栈代码
检查正在运行的进程在做什么:未仪表化的Python程序的打印堆栈跟踪
#1 楼
我有用于以下情况的模块-进程将长时间运行,但有时由于未知且不可复制的原因而卡住。它有点黑,只能在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食谱。 />
评论
谢谢!这就是我想要的。也许您也可以在一些Python摘录网站上发布带有管道支持的脚本?
–Seb
08-09-25在16:39
我现在已经将其发布在python Cookbook网站上-添加了链接。
–布赖恩
08-09-25在18:08
我需要添加“导入阅读行”以启用历史记录功能。
– miiracle2k
09年11月16日在9:54
大提示!这也可以将信号发送到包含单词“ mypythonapp”的所有进程:pkill -SIGUSR1 -f mypythonapp
–亚历山大
2010年8月5日9:29
如果应用程序被卡住,Python解释器循环可能无法运行以处理信号。使用Faulthandler模块(及其在PyPI上找到的反向端口)进行C级信号处理程序,该处理程序将打印Python堆栈,而无需解释器循环作出响应。
–gps
2014年1月14日在20:08
#2 楼
安装信号处理程序的建议是一个很好的建议,我经常使用它。例如,默认情况下,bzr安装一个SIGQUIT处理程序,该处理程序调用pdb.set_trace()
以立即将您放入pdb提示符。 (有关详细信息,请参见bzrlib.breakin模块的源代码。)使用pdb,您不仅可以获取当前的堆栈跟踪(使用(w)here
命令),还可以检查变量等。但是,有时我需要调试我没有先见之明的进程来安装信号处理程序。在linux上,您可以将gdb附加到进程上,并使用一些gdb宏获取python堆栈跟踪。将http://svn.python.org/projects/python/trunk/Misc/gdbinit放入
~/.gdbinit
中,然后:附加gdb:
gdb -p
PID
获取python堆栈跟踪:
pystack
不幸的是,它并不是完全可靠的,但是在大多数情况下都可以使用。
最后,附加
strace
通常可以使您很好地了解过程的执行情况。 评论
辉煌! pystack命令有时会锁定,但是在执行此操作之前,它无需使用任何准备即可在python代码行中为我提供该过程的完整堆栈跟踪。
– Muudscope
2010年5月5日7:07
较小的更新:Wiki.python.org/moin/DebuggingWithGdb记录了此gdb技术(和更新的代码),该方面已有一些开发,并记录在该URL上,并且gdb 7显然具有Python支持。
–尼尔森
2011年9月24日在1:24
据我所知,这只有在将调试符号编译到python二进制文件中时才有效-例如:您使用python2-dbg(在Ubuntu上,这是在单独的软件包python-dbg中)运行程序。没有这些符号,您似乎看不到很多有用的信息。
– drevicko
13年2月21日,下午3:51
在我的情况下,此返回无法找到每个命令的python框架
–seriyPS
2014年1月22日15:49
gdb 7+ --with-python支持由python-gdb.py提供。此处有更多详细信息:chezsoi.org/lucas/blog/2014/11/07/en-gdb-python-macros
–卢卡斯·西蒙(Lucas Cimon)
2014年11月7日14:24
#3 楼
我几乎总是与多个线程打交道,而主线程通常不会做很多事情,所以最有趣的是转储所有堆栈(这更像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)
#4 楼
使用pyrasite可以获取未准备的python程序的堆栈跟踪,并在没有调试符号的情况下在现有的python中运行。在Ubuntu Trusty上对我来说像是一种魅力:$ sudo pip install pyrasite
$ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
$ sudo pyrasite 16262 dump_stacks.py # dumps stacks to stdout/stderr of the python program
(@Albert的提示,以及其他工具,其答案包含了对此的指针。)
评论
这对我来说非常有用,在这里dump_stacks.py只是导入回溯。 traceback.print_stack()
–约翰·莱曼(John Lehmann)
15年6月2日在15:48
traceback -l为您提供了可以使用的预定义python脚本列表,dump_stacks.py是其中之一。如果您使用自己的名称(例如,将堆栈跟踪信息写入文件),则最好使用其他名称。
–johndodo
2015年11月11日上午10:14
重要提示:在运行pyrasite之前运行apt-get install gdb python-dbg(或同等功能),否则它将无提示地失败。否则就像魅力!
–johndodo
2015年11月11日10:56
吡a酸酯的最新释放是在2012年
–鲍里斯(Boris)
20-5-30在22:22
#5 楼
>>> import traceback
>>> def x():
>>> print traceback.extract_stack()
>>> x()
[('<stdin>', 1, '<module>', None), ('<stdin>', 2, 'x', None)]
还可以很好地设置堆栈跟踪的格式,请参阅文档。
编辑:如@Douglas Leeder所建议,要模拟Java的行为,请添加以下内容:
import signal
import traceback
signal.signal(signal.SIGUSR1, lambda sig, stack: traceback.print_stack(stack))
应用程序中的启动代码。然后,您可以通过向正在运行的Python进程发送
SIGUSR1
来打印堆栈。评论
这只会打印主线程的回溯。我尚未找到用于查看所有线程跟踪的解决方案。实际上,尽管threading.enumerate()允许访问所有Thread对象,但python似乎缺少从Thread对象检索堆栈的API。
–haridsv
2010-4-2 22:48
这在cygwin上效果很好。虽然它仅打印三行堆栈跟踪,但这足以获取线索
– slashdottir
13-10-14在18:17
#6 楼
追溯模块具有一些不错的功能,其中包括:print_stack:import traceback
traceback.print_stack()
评论
要将堆栈跟踪写出到文件,请使用:import traceback; f =打开('/tmp/stack-trace.log','w')traceback.print_stack(file = f)f.close()
–GuruM
2012年8月16日9:25
+1到@gulgi以获得简单易用的答案。对于我从脚本函数中获取调用堆栈跟踪的简单任务,其他一些答案看起来非常复杂。
–GuruM
2012年8月16日在9:28
#7 楼
您可以尝试使用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/
#8 楼
spiv的技巧(如果我有信誉点,我会投赞成票并进行评论),这对我真正的帮助是从未经准备的Python流程中获取堆栈跟踪。除非在我修改gdbinit脚本之前它不起作用。因此:下载http://svn.python.org/projects/python/trunk/Misc/gdbinit并将其放在
~/.gdbinit
中进行编辑,将
PyEval_EvalFrame
更改为PyEval_EvalFrameEx
[编辑:不再需要;链接的文件在2010年1月14日已经有了此更改] 附加gdb:
gdb -p PID
获取python堆栈跟踪:
pystack
评论
提到的URL上的gdbinit似乎已经具有您建议的补丁。就我而言,当我键入pystack时,我的CPU刚刚挂起。不知道为什么。
–杰西·格里克(Jesse Glick)
09年7月21日在21:23
不,不是这样,我不清楚,抱歉,因为该行出现在三个地方。我链接到的补丁程序显示了当我看到此工作时我更改了哪个。
– Gunnlaugur Briem
09年7月23日在13:34
就像@spiv的答案一样,这要求程序在使用调试符号编译的python下运行。否则,您将在当前上下文中仅获得No符号“ co”。
– Nickolay
2015年4月26日17:50
#9 楼
python -dv yourscript.py这将使解释器在调试模式下运行,并为您提供解释器正在执行的操作的跟踪信息。
如果要进行交互调试代码,您应该像这样运行它:
python -m pdb yourscript.py
这告诉python解释器使用模块“ pdb”运行脚本python调试器,如果您像这样运行它,解释器将以交互模式执行,就像GDB
评论
这不能回答问题。问题是关于一个已经在运行的进程。
–dbn
2014年10月8日18:47
#10 楼
我会将其添加为haridsv的评论,但我缺乏这样做的声誉:我们中有些人仍然停留在2.6之前的python版本(Thread.ident必需),因此我得到了在Python 2.5中运行的代码(尽管未显示线程名称),如下所示:
import traceback
import sys
def dumpstacks(signal, frame):
code = []
for threadId, stack in sys._current_frames().items():
code.append("\n# Thread: %d" % (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)
#11 楼
看一下Python 3.3中新增的faulthandler
模块。 PyPI上提供了在Python 2中使用的faulthandler
反向端口。评论
@haypo的最新答案对此进行了更详细的介绍。我不确定这在SO上通常是如何处理的,但是有两个基本上重复的答案是错误的……
– Nickolay
15年4月26日在17:56
#12 楼
在Solaris上,可以使用pstack(1)无需更改python代码。例如# pstack 16000 | grep : | head
16000: /usr/bin/python2.6 /usr/lib/pkg.depotd --cfg svc:/application/pkg/serv
[ /usr/lib/python2.6/vendor-packages/cherrypy/process/wspbus.py:282 (_wait) ]
[ /usr/lib/python2.6/vendor-packages/cherrypy/process/wspbus.py:295 (wait) ]
[ /usr/lib/python2.6/vendor-packages/cherrypy/process/wspbus.py:242 (block) ]
[ /usr/lib/python2.6/vendor-packages/cherrypy/_init_.py:249 (quickstart) ]
[ /usr/lib/pkg.depotd:890 (<module>) ]
[ /usr/lib/python2.6/threading.py:256 (wait) ]
[ /usr/lib/python2.6/Queue.py:177 (get) ]
[ /usr/lib/python2.6/vendor-packages/pkg/server/depot.py:2142 (run) ]
[ /usr/lib/python2.6/threading.py:477 (run)
etc.
评论
似乎有一个Debian / Ubuntu程序pstack可以完成相同的操作
–Rory
2011-12-30 11:47
似乎只在Linux下提供回溯,而没有提供文件名和行号的Python回溯。
– ogrisel
13年10月30日在21:50
#13 楼
如果您使用的是Linux系统,请使用gdb
的出色功能和Python调试扩展名(可以在python-dbg
或python-debuginfo
软件包中)。它还对多线程应用程序,GUI应用程序和C模块有帮助。使用以下命令运行程序:
$ gdb -ex r --args python <programname>.py [arguments]
这指示
gdb
准备python <programname>.py <arguments>
和现在,当程序挂起时,切换到
r
控制台,按Ctr + C并执行:(gdb) thread apply all py-list
请参阅示例会话以及此处和此处的更多信息。
#14 楼
我一直在寻找调试我的线程的解决方案,由于haridsv在这里找到了它。我使用使用traceback.print_stack()的稍微简化的版本: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)
为了满足我的需要,我还按名称过滤了线程。#15 楼
可以使用出色的py-spy完成。它是Python程序的采样分析器,因此它的工作是附加到Python进程并对其调用堆栈进行采样。因此,在转储py-spy dump --pid $SOME_PID
进程中所有线程的调用堆栈时,只需要做$SOME_PID
。通常,它需要升级的特权(以读取目标进程的内存)。 这是一个线程化Python应用程序的外观示例。
$ sudo py-spy dump --pid 31080
Process 31080: python3.7 -m chronologer -e production serve -u www-data -m
Python v3.7.1 (/usr/local/bin/python3.7)
Thread 0x7FEF5E410400 (active): "MainThread"
_wait (cherrypy/process/wspbus.py:370)
wait (cherrypy/process/wspbus.py:384)
block (cherrypy/process/wspbus.py:321)
start (cherrypy/daemon.py:72)
serve (chronologer/cli.py:27)
main (chronologer/cli.py:84)
<module> (chronologer/__main__.py:5)
_run_code (runpy.py:85)
_run_module_as_main (runpy.py:193)
Thread 0x7FEF55636700 (active): "_TimeoutMonitor"
run (cherrypy/process/plugins.py:518)
_bootstrap_inner (threading.py:917)
_bootstrap (threading.py:885)
Thread 0x7FEF54B35700 (active): "HTTPServer Thread-2"
accept (socket.py:212)
tick (cherrypy/wsgiserver/__init__.py:2075)
start (cherrypy/wsgiserver/__init__.py:2021)
_start_http_thread (cherrypy/process/servers.py:217)
run (threading.py:865)
_bootstrap_inner (threading.py:917)
_bootstrap (threading.py:885)
...
Thread 0x7FEF2BFFF700 (idle): "CP Server Thread-10"
wait (threading.py:296)
get (queue.py:170)
run (cherrypy/wsgiserver/__init__.py:1586)
_bootstrap_inner (threading.py:917)
_bootstrap (threading.py:885)
评论
这行得通,但是来自@kmaork答案的hypno会产生Python回溯,这对于弄清楚问题出在哪里更加有用。
– Kiran Jonnalagadda
20年9月9日在9:41
#16 楼
值得一看的是Pydb,“它是基于gdb命令集的宽松版本的Python调试器的扩展版本”。它包括信号管理器,可以在发送指定信号时负责启动调试器。2006年夏天的Code项目研究了在名为mpdb的模块中为pydb添加远程调试功能。
评论
似乎它经历了两(1)次重写(2),没有添加我一直在寻找的PID附加功能...
– Nickolay
15年4月26日在18:01
#17 楼
我一起破解了一些附加到正在运行的Python进程中的工具,并注入了一些代码来获取Python Shell。请参见此处:https://github.com/albertz/pydbattach
评论
注意:如何构建它并不明显。不过,感谢您在自述文件中提供的链接:pyrasite效果很好!
– Nickolay
15年4月26日在17:47
#18 楼
pyringe是一个调试器,可以与运行中的python进程,打印堆栈跟踪,变量等进行交互,而无需任何先验设置。我过去经常使用信号处理程序解决方案,但它可以在某些环境中仍然常常很难重现该问题。
评论
显然,它与某些gdb构建不兼容(例如我在ubuntu上安装的gdb构建):github.com/google/pyringe/issues/16,需要手动重建。另一个调试器pyrasite对我来说就像一个魅力。
– Nickolay
15年4月26日在18:09
#19 楼
没有办法挂接到正在运行的python进程中并获得合理的结果。如果进程锁定了,我该怎么做,就是钩住strace并试图弄清楚到底发生了什么。不幸的是,strace常常是观察者“修复”竞争条件,因此输出在那里也没有用。
评论
是的,这是真的。尽管该pdb不支持附加到正在运行的进程,但真是令人遗憾。
– BartoszRadaczyński
08-09-25 at 10:15
这不是真的。请参阅上面“ spiv”的答案,其中显示了如何连接gdb并获取Python堆栈跟踪。
– andrew cooke
2010年5月31日13:45
这是不一样的-这些gdb宏不可靠,并且不提供pdb的完整功能/熟悉的接口。我经常希望有人编写一个小型应用程序,该应用程序将使用ptrace将一些Python字节码注入正在运行的Python进程中,并使其执行'import pdb; pdb.set_trace()”,也可能在临时重定向sys.stdin / stdout之后。
– Marius Gedminas
10年8月24日在22:42
这不再是真的,请参见指向吡咯/吡喃石的其他答案。
– Nickolay
15年4月26日在18:26
#20 楼
您可以使用PuDB(具有curses接口的Python调试器)来执行此操作。只需在代码中添加from pudb import set_interrupt_handler; set_interrupt_handler()
,然后在需要中断时使用Ctrl-C。您可以继续使用
c
,如果错过了并想再试一次,请再次中断多次。 评论
在Django中使用上述命令时,请不要忘记正确运行服务器以防止故障:“ manage.py runserver --noreload --nothreading”
–钾盐
2015年2月13日在10:55
#21 楼
我在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
。评论
是否会得到类似Traceback(最近一次调用的响应)这样的响应是否正常:Python异常
–crookedleaf
18年8月15日在20:08
没关系。这是因为我的应用程序以sudo运行。我也需要以sudo的身份运行gdb python
–歪叶
18年8月15日在20:11
#22 楼
如何在控制台中调试任何功能:在使用pdb.set_trace()的地方创建函数,然后在要调试的函数上进行调试。
>>> import pdb
>>> import my_function
>>> def f():
... pdb.set_trace()
... my_function()
...
然后调用创建的函数:
>>> f()
> <stdin>(3)f()
(Pdb) s
--Call--
> <stdin>(1)my_function()
(Pdb)
调试愉快:)
#23 楼
您可以使用hypno包,如下所示:hypno <pid> "import traceback; traceback.print_stack()"
这会将堆栈跟踪信息打印到程序的stdout中。
或者,如果您不想打印任何内容到stdout,或者如果没有访问权限(例如,守护程序),则可以使用madbg软件包,该软件包是python调试器,可让您附加到正在运行的python程序并在当前终端中对其进行调试。它类似于
pyrasite
和pyringe
,但是更新,不需要gdb,并且使用IPython
作为调试器(这意味着颜色和自动完成功能)。要查看正在运行的程序的堆栈跟踪,可以运行:
madbg attach <pid>
然后在调试器外壳中输入:
bt
免责声明-我写了两个软件包
评论
FTW! sudo $(哪个hypno)$(pgrep pytest)“导入跟踪; traceback.print_stack()”(即使两个进程都由同一用户拥有,没有sudo也无法工作。)
– Kiran Jonnalagadda
20/09/9在9:38
很高兴听到!如果您允许在计算机上使用ptrace范围,它可以在没有sudo的情况下工作,更多详细信息请参见:stackoverflow.com/q/19215177/2907819
– kmaork
20/09/11于13:30
#24 楼
我不知道有什么类似于Java对SIGQUIT的响应,因此您可能必须将其内置到应用程序中。也许您可以在另一个线程中创建一个服务器,该服务器可以在响应某种消息时获得堆栈跟踪?#25 楼
使用检查模块。导入检查
help(inspect.stack)
模块检查中的功能堆栈帮助:
stack(context = 1)
返回调用者框架上方的堆栈的记录列表。
我发现它确实很有帮助。
#26 楼
在Python 3中,第一次在调试器中使用c(ont(inue))时,pdb将自动安装信号处理程序。之后按Control-C将使您回到原来的位置。在Python 2中,这是一个单行代码,即使在相对较旧的版本中也可以使用(在2.7中进行了测试,但我检查了Python源代码回到2.4,看起来还可以):import pdb, signal
signal.signal(signal.SIGINT, lambda sig, frame: pdb.Pdb().set_trace(frame))
#27 楼
如果您需要使用uWSGI进行此操作,它内置了Python Tracebacker,只需在配置中启用它即可(每个工人的名字都附有数字):py-tracebacker=/var/run/uwsgi/pytrace
完成此操作后,只需连接到套接字即可打印回溯记录:
uwsgi --connect-and-read /var/run/uwsgi/pytrace1
#28 楼
在运行代码的那一点,您可以插入此小片段,以查看格式正确的打印堆栈跟踪。假定您在项目的根目录中有一个名为logs
的文件夹。 # DEBUG: START DEBUG -->
import traceback
with open('logs/stack-trace.log', 'w') as file:
traceback.print_stack(file=file)
# DEBUG: END DEBUG --!
评论
相关:stackoverflow.com/q/4163964/1449460相关的wiki.python.org/moin/DebuggingWithGdb