出错时自动启动python调试器

时间:2008-10-28 07:37:16

标签: python debugging

这是我一直想知道的一个问题,但我从来没有找到合适的解决方案。如果我运行一个脚本并且遇到了,那么就说一个IndexError,python打印出错误的行,位置和快速描述并退出。遇到错误时是否可以自动启动pdb?我并不反对在文件顶部添加额外的import语句,也不反对添加一些额外的代码行。

14 个答案:

答案 0 :(得分:365)

python -m pdb -c continue myscript.py

如果你没有提供-c continue标志,那么你需要在执行开始时输入'c'(表示继续)。然后它将运行到错误点并让你控制那里。作为mentioned by eqzx,这个标志是python 3.2中的新增加,因此早期Python版本需要输入'c'(参见https://docs.python.org/3/library/pdb.html)。

答案 1 :(得分:107)

您可以使用traceback.print_exc打印例外追溯。然后使用sys.exc_info提取回溯,最后使用该回溯调用pdb.post_mortem

import pdb, traceback, sys

def bombs():
    a = []
    print a[0]

if __name__ == '__main__':
    try:
        bombs()
    except:
        extype, value, tb = sys.exc_info()
        traceback.print_exc()
        pdb.post_mortem(tb)

如果要使用code.interact启动交互式命令行,请使用发生异常的帧的本地,

import traceback, sys, code

def bombs():
    a = []
    print a[0]

if __name__ == '__main__':
    try:
        bombs()
    except:
        type, value, tb = sys.exc_info()
        traceback.print_exc()
        last_frame = lambda tb=tb: last_frame(tb.tb_next) if tb.tb_next else tb
        frame = last_frame().tb_frame
        ns = dict(frame.f_globals)
        ns.update(frame.f_locals)
        code.interact(local=ns)

答案 2 :(得分:59)

使用以下模块:

import sys

def info(type, value, tb):
    if hasattr(sys, 'ps1') or not sys.stderr.isatty():
    # we are in interactive mode or we don't have a tty-like
    # device, so we call the default hook
        sys.__excepthook__(type, value, tb)
    else:
        import traceback, pdb
        # we are NOT in interactive mode, print the exception...
        traceback.print_exception(type, value, tb)
        print
        # ...then start the debugger in post-mortem mode.
        # pdb.pm() # deprecated
        pdb.post_mortem(tb) # more "modern"

sys.excepthook = info

将其命名为debug(或您喜欢的任何内容)并将其放在python路径中的某处。

现在,在脚本开头,只需添加import debug

答案 3 :(得分:36)

Ipython 有一个切换此行为的命令:%pdb 。它完全符合您的描述,甚至可能更多(通过语法突出显示和代码完成为您提供更多信息性回溯)。这绝对值得一试!

答案 4 :(得分:30)

这不是调试器,但可能同样有用(?)

我知道我听到Guido在某个地方的演讲中提到了这一点。

我刚检查了python - ?,如果使用-i命令,则可以在脚本停止的位置进行交互。

所以给出了这个脚本:

testlist = [1,2,3,4,5, 0]

prev_i = None
for i in testlist:
    if not prev_i:
        prev_i = i
    else:
        result = prev_i/i

你可以得到这个输出!

PS D:\> python -i debugtest.py
Traceback (most recent call last):
  File "debugtest.py", line 10, in <module>
    result = prev_i/i
ZeroDivisionError: integer division or modulo by zero
>>>
>>>
>>> prev_i
1
>>> i
0
>>>

老实说,我没有用过这个,但我应该,似乎非常有用。

答案 5 :(得分:17)

IPython在命令行上使这个变得简单:

python myscript.py arg1 arg2

可以改写为

ipython --pdb myscript.py -- arg1 arg2

或者,类似地,如果调用模块:

python -m mymodule arg1 arg2

可以改写为

ipython --pdb -m mymodule -- arg1 arg2

注意--阻止IPython将脚本的参数作为自己的参数。

这也有一个优点,就是调用增强的IPython调试器(ipdb)而不是pdb。

答案 6 :(得分:6)

如果您正在使用IPython环境,您可以使用%debug,shell将带您回到带有ipdb环境的违规行以进行检查等。另一个选项如上所述是使用iPython magic%pdb这实际上也是如此。

答案 7 :(得分:4)

您可以在代码中添加以下内容:

import pdb ; pdb.set_trace()

更多信息:Start the python debugger at any line

答案 8 :(得分:4)

如果您使用的是ipython,请在启动后输入%pdb

In [1]: %pdb
Automatic pdb calling has been turned ON

答案 9 :(得分:3)

要让它在开始时无需输入c即可运行:

python -m pdb -c c <script name>

Pdb有自己的命令行参数:-c c将在执行开始时执行c(ontinue)命令,程序将不间断地运行直到出错。

答案 10 :(得分:2)

在python2.7中的python -m pdb script.py按继续启动它将运行错误并在那里进行调试。

答案 11 :(得分:0)

在层次结构中最顶层异常类的构造函数中放置一个断点,并且大多数时候您将看到引发错误的位置。

设置断点意味着您想要的意思:您可以使用IDE,或pdb.set_trace,或其他

答案 12 :(得分:0)

如果您正在运行模块:

python -m mymodule

现在您想在发生异常时输入pdb,请执行以下操作:

PYTHONPATH="." python -m pdb -c c mymodule/__main__.py

(或扩展您的PYTHONPATH)。由于您现在正在运行PYTHONPATH模块,因此需要pdb以便在路径中找到模块。

答案 13 :(得分:0)

ipdb 有一个很好的上下文管理器来实现这种行为,使意图在语义上更清晰:

from ipdb import launch_ipdb_on_exception

with launch_ipdb_on_exception():
    ...