Python - 当出现异常时启动交互式调试器

22

有没有办法让 Python 程序启动交互式调试器,就像 import pdb; pdb.set_trace() 这样的方式,而不是实际抛出异常?

我知道这样做的难度,但这比在巨大的堆栈跟踪后使用它来找出在哪里插入断点然后重新启动程序进行调试更有价值。我知道仅仅是让调试器启动而不抛出异常是没有意义的,因为任何异常都可以在某个层次上被捕捉到,所以如果我可以选择一些异常,让它们启动交互式调试会话而不是被抛出(因为我知道这个列表中的异常确实是“错误”,没有有意义的程序行为可以继续执行)...

我听说 Common Lisp 有类似的东西,但我不知道它具体是如何工作的,只知道“真正的 Lisper”非常赞扬它...


1
这个问题看起来非常类似于:在错误发生时自动启动Python调试器,那里有更好的答案。 - Calimo
4个回答

19
最简单的方法是将您的整个代码放在一个try块中,就像这样:
if __name__ == '__main__':

    try:
        raise Exception()
    except:
        import pdb
        pdb.set_trace()

还有一种更复杂的解决方案,它使用sys.excepthook来覆盖未捕获异常的处理方式,如此处的示例所述:

## {{{ http://code.activestate.com/recipes/65287/ (r5)
# code snippet, to be included in 'sitecustomize.py'
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()

sys.excepthook = info
## end of http://code.activestate.com/recipes/65287/ }}}

以上代码应该包含在一个名为 sitecustomize.py 的文件中,该文件位于 site-packages 目录中,并由 Python 自动导入。只有在非交互模式下运行 Python 时才会启动调试器。

1
就你提到的第二个例子而言,我的意思是我不想修改现有的程序代码:是的,但我想要的是调试器动态插入断点并启动“实时”调试器,而不是抛出异常(防止它被抛出或其他操作),而不是“事后诸葛亮”。 - NeuronQ
1
@NeuronQ 你试过用 pdb.set_trace() 替换 pdb.pm() 吗?这应该可以解决问题。 - Boris Gorelik
@NeuroQ 请看我的回答,了解如何在不进行任何系统修改的情况下完成此操作。 - Bryce Guinta

10

这个问题非常古老,所以主要是为了未来的我

try:
    ...
except:
    import traceback, pdb, sys
    traceback.print_exc()
    print ''
    pdb.post_mortem()
    sys.exit(1)

谢谢!这非常有帮助,我知道这是可能的,而且正是我所需要的。 - Brian Peterson

2
我写了一个程序包,用于在出现异常时启动pdb。它使用了@boreis-gorelik的答案,并在运行时修改解释器状态,因此不需要进行任何代码更改:

安装

 pip install mort

用法

mort <file.py or module to execute>

当出现异常时,pdb repl 应该在给定的终端中启动。

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接