在出错时自动启动Python调试器

299 投票
15 回答
125409 浏览
提问于 2025-04-11 09:36

我一直在想一个问题,但一直找不到合适的解决办法。假设我运行一个脚本,结果遇到了一个索引错误(IndexError),这时Python会打印出出错的行号、位置和简单的错误描述,然后程序就结束了。我想知道有没有办法在遇到错误时自动启动调试工具pdb?我并不介意在文件顶部多加一个导入语句,或者多写几行代码。

15 个回答

77

使用下面这个模块:

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 这一行。

624
python -m pdb -c continue myscript.py
# or
python -m pdb -c continue -m myscript

如果你不加 -c continue 这个选项,那么在程序开始执行时,你需要输入 'c'(表示继续)。这样程序会运行到出错的地方,然后让你在那儿控制程序。正如 eqzx 提到的,这个选项是在 Python 3.2 版本中新增的,所以在更早的 Python 版本中,你必须输入 'c'(继续)才能继续执行(详细信息可以查看 https://docs.python.org/3/library/pdb.html)。

161

你可以使用 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)

如果你想要在出现异常的地方启动一个交互式命令行,并使用当时的局部变量,可以这样做:

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)

撰写回答