【问题标题】:Python - start interactive debugger when exception would be otherwise thrownPython - 否则会引发异常时启动交互式调试器
【发布时间】:2012-10-21 21:11:49
【问题描述】:

有什么方法可以让python程序启动一个交互式调试器,比如import pdb; pdb.set_trace()而不是实际抛出异常?

我知道完成这项工作的难度,但它比巨大的堆栈跟踪更有价值,之后我必须使用它来确定在哪里插入断点,然后重新启动程序来调试它。我知道简单地启动调试器而不是抛出异常是没有意义的,因为任何异常都可以在一个级别或另一个级别上捕获,所以 如果我可以选择一个交互式调试会话将启动的异常列表而不是它们被抛出(因为我知道此列表中的异常确实是“错误”,之后不会出现有意义的程序行为)...

我听说 Common Lisp 有这样的东西,但我不知道它是如何工作的,只是“真正的 lispers” 对它赞不绝口......

【问题讨论】:

标签: python debugging pdb


【解决方案1】:

我写了a package 以在异常时启动 pdb。它接受@boreis-gorelik 的回答,并在运行时修改解释器状态,因此无需更改代码:

安装

 pip install mort

用法

mort <file.py or module to execute>

当异常发生时,pdb repl 应该在给定的终端启动

【讨论】:

    【解决方案2】:

    最简单的方法是将整个代码包装在 try 块中,如下所示:

    if __name__ == '__main__':
    
        try:
            raise Exception()
        except:
            import pdb
            pdb.set_trace()
    

    有一个更复杂的解决方案,它使用sys.excepthook 来覆盖对未捕获异常的处理,如this recipe 中所述:

    ## {{{ 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/ }}}
    

    上面的代码应该包含在site-packages目录下名为sitecustomize.py的文件中,该文件由python自动导入。调试器仅在 python 以非交互模式运行时启动。

    【讨论】:

    • 指的是你的第二个例子,因为这就是我的意思,我不想修改现有的程序代码:是的,但我想要的是让调试器动态插入一个断点并启动“实时”调试器而不是抛出异常(防止它被抛出或smth)而不是“事后”
    • @NeuronQ 您是否尝试将pdb.pm() 替换为pdb.set_trace()?这应该工作
    • @NeuroQ 查看我的答案,了解如何在不进行任何系统修改的情况下执行此操作
    【解决方案3】:

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

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

    【讨论】:

    • 谢谢!这很有帮助,我知道这是可能的,这正是我所需要的。
    【解决方案4】:

    如果你在 REPL 里面,你可以这样做

    import sys
    import pdb
    pdb.post_mortem(sys.last_traceback)
    

    https://docs.python.org/2/library/pdb.htmlhttps://docs.python.org/3/library/traceback.html

    【讨论】:

      猜你喜欢
      • 2022-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-03
      • 1970-01-01
      • 1970-01-01
      • 2017-03-30
      • 1970-01-01
      相关资源
      最近更新 更多