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

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

某种飞行中的堆叠痕迹?

相关问题:

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


当前回答

看一下Python 3.3中新增的faulthandler模块。PyPI上有一个用于Python 2的faulthandler backport。

其他回答

在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))

如果你花时间调试Python, pdb是值得学习的。这个界面有点迟钝,但是对于使用过类似工具(比如gdb)的人来说应该很熟悉。

如何调试任何函数在控制台:

创建使用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) 

愉快的调试:)

>>> import traceback
>>> def x():
>>>    print traceback.extract_stack()

>>> x()
[('<stdin>', 1, '<module>', None), ('<stdin>', 2, 'x', None)]

您还可以很好地格式化堆栈跟踪,请参阅文档。

编辑:为了模拟Java的行为,正如道格拉斯·里德所建议的那样,添加以下内容:

import signal
import traceback

signal.signal(signal.SIGUSR1, lambda sig, stack: traceback.print_stack(stack))

到应用程序中的启动代码。然后,您可以通过将SIGUSR1发送到正在运行的Python进程来打印堆栈。

traceback模块有一些不错的函数,其中包括:

import traceback

traceback.print_stack()

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

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

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

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

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

madbg attach <pid>

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

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