出错时自动启动python调试器

jer*_*emy 194 python debugging

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

Cat*_*lin 399

python -m pdb -c continue myscript.py
Run Code Online (Sandbox Code Playgroud)

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

  • 请OP,接受这个作为答案.这是最有用的,我浪费了5分钟阅读其他的,直到我点击这个...这应该是第一个! (31认同)
  • 这不适用于Python 2.7.https://docs.python.org/3/library/pdb.html:"版本3.2中的新功能:pdb.py现在接受执行命令的-c选项" (18认同)
  • 谢谢你提到"_enter'c'_" - 我通常用来输入'r'(用于"run"),从`gdb`开始使用它.当你在`pdb`中输入'r'时,程序确实会运行,但不会在出错时停止(也不会生成回溯); 让我感到困惑,直到我读到这个.干杯! (4认同)
  • Vineet,它将启动调试器,因此输入"cont"它将一直运行,直到遇到错误.从那里你可以检查变量等,就像在任何其他pdb会话中一样. (3认同)
  • 这对于`ipdb`也是一样的.当然可以在脚本之后添加参数! (3认同)
  • 我尝试过你的方法。但是它似乎没有提供任何真正的控制,例如在发生错误时检查变量。它似乎提供的唯一选择是重新开始执行。 (2认同)

Flo*_*sch 114

您可以使用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)
Run Code Online (Sandbox Code Playgroud)

如果您想使用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)
Run Code Online (Sandbox Code Playgroud)

  • *然后使用`sys.exc_info`提取回溯,最后使用该回溯调用`pdb.post_mortem`。您不需要将回溯对象传递给 `pdb.post_mortem`。来自 [docs](https://docs.python.org/2/library/pdb.html):*如果没有给出回溯,它使用当前正在处理的异常之一(必须正在处理异常如果要使用默认值)。* (4认同)
  • 为什么有人会更喜欢"代码"而不是"pdb",因为后者似乎扩展了前者? (3认同)
  • @PiotrDobrogost 好点。我认为知道您可以传入 tb 对象更有帮助,因为它可以更好地演示 API。很高兴知道这两种选择都存在。 (2认同)

tzo*_*zot 63

使用以下模块:

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
Run Code Online (Sandbox Code Playgroud)

将它命名debug(或任何你喜欢的)并将其放在python路径中的某个位置.

现在,在脚本开始时,只需添加一个import debug.

  • 这应该是公认的答案-它不需要修改现有代码,也不需要将所有内容都包裹在“ try-catch”中,而这只是丑陋的IMO。 (2认同)

Lat*_*ius 41

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

  • 记录在http://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-pdb (4认同)
  • 请注意 - 正如文档中提到的@matthiash链接 - "%debug"允许用户打开调试器_after_遇到错误.我经常比`%pdb`更喜欢这个.(每次你想要调试错误时,每次你不想调试错误时都要输入`q`而不是输入'%debug`.) (4认同)
  • 这是对此的唯一合理答案。 (3认同)
  • 还要注意,在`ipython_config.py` 中设置`c.InteractiveShell.pdb = True` 会为每个会话自动打开`%pdb`。 (3认同)

mon*_*kut 31

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

我知道我听到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
Run Code Online (Sandbox Code Playgroud)

你可以得到这个输出!

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
>>>
Run Code Online (Sandbox Code Playgroud)

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

  • 不太有用,推出全球范围.无论什么功能崩溃都无法解决. (7认同)

wod*_*dow 19

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

python myscript.py arg1 arg2
Run Code Online (Sandbox Code Playgroud)

可以改写成

ipython --pdb myscript.py -- arg1 arg2
Run Code Online (Sandbox Code Playgroud)

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

python -m mymodule arg1 arg2
Run Code Online (Sandbox Code Playgroud)

可以改写成

ipython --pdb -m mymodule -- arg1 arg2
Run Code Online (Sandbox Code Playgroud)

注意--停止IPython读取脚本的参数作为它自己的参数.

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


Jeh*_*dad 6

如果你正在使用IPython环境,你可以使用%debug,shell将带你回到带有ipdb环境的违规行以进行检查等.如上所述,另一个选项是使用iPython magic%pdb相同.


Wil*_*oes 6

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

In [1]: %pdb
Automatic pdb calling has been turned ON
Run Code Online (Sandbox Code Playgroud)


小智 5

要使其运行而不必在开始时键入 c,请使用:

python -m pdb -c c <script name>
Run Code Online (Sandbox Code Playgroud)

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