Starting python debugger automatically on error
这是一个我思考了很长时间的问题,但我从未找到合适的解决方案。如果我运行一个脚本,遇到一个索引错误,那么Python将打印该错误的行、位置和快速描述,然后退出。遇到错误时是否可以自动启动PDB?我不反对在文件的顶部有一个额外的导入语句,也不反对有一些额外的代码行。
1 | python -m pdb -c continue myscript.py |
如果不提供
您可以使用traceback.print_exc来打印异常的traceback。然后使用sys.exc_info提取回溯,最后使用该回溯调用pdb.post_mortem
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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启动一个交互式命令行,可以使用产生异常的帧的局部变量进行交互。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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) |
使用以下模块:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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) # ...then start the debugger in post-mortem mode. # pdb.pm() # deprecated pdb.post_mortem(tb) # more"modern" sys.excepthook = info |
把它命名为
现在,在脚本的开头,只需添加一个
IPython有一个用于切换此行为的命令:%pdb。它完全符合您所描述的,甚至更多(通过语法突出显示和代码完成为您提供更丰富的回溯信息)。这绝对值得一试!
这不是调试器,但可能同样有用(?)
我知道我在某个地方的演讲中听到吉多提到这个。
我刚检查过python-?如果使用-i命令,则可以在脚本停止的位置进行交互。
因此,根据这个脚本:
1 2 3 4 5 6 7 8 | 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 |
你可以得到这个输出!
1 2 3 4 5 6 7 8 9 10 11 12 | 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 >>> |
老实说,我没有用过这个,但我应该用,看起来很有用。
ipython在命令行中简化了这一点:
1 | python myscript.py arg1 arg2 |
可重写为
1 | ipython --pdb myscript.py -- arg1 arg2 |
或者,类似地,如果调用模块:
1 | python -m mymodule arg1 arg2 |
可重写为
1 | ipython --pdb -m mymodule -- arg1 arg2 |
注意
这还具有调用增强的IPython调试器(IPDB)而不是PDB的优势。
如果您使用的是IPython环境,那么您只需使用%debug,shell将带您返回到与IPDB环境冲突的行进行检查等。上面提到的另一个选项是使用IPython magic%pdb,它有效地做到了这一点。
如果您正在使用
1 2 | In [1]: %pdb Automatic pdb calling has been turned ON |
您可以将此行放入代码中:
1 | import pdb ; pdb.set_trace() |
更多信息:在任意行启动python调试器
要使其运行而不必在开始时键入c,请执行以下操作:
7pdb有自己的命令行参数:-c c将在执行开始时执行c(c ontinue)命令,并且程序将不间断运行,直到出现错误为止。
python2.7中的python-m pdb script.py按"继续"以启动,它将运行到错误处并在那里中断以进行调试。
如果正在运行模块:
1 | python -m mymodule |
现在,您要在发生异常时输入
1 | PYTHONPATH="." python -m pdb -c c mymodule/__main__.py |
(或扩展您的
在层次结构中最顶层异常类的构造函数中放置一个断点,大多数情况下,您将看到错误出现在哪里。
放置一个断点意味着你想要它意味着什么:你可以使用一个IDE,或者