这是我一直想知道的一个问题,但我从来没有找到合适的解决方案。如果我运行一个脚本并且遇到了,那么就说一个IndexError,python打印出错误的行,位置和快速描述并退出。遇到错误时是否可以自动启动pdb?我并不反对在文件顶部添加额外的import语句,也不反对添加一些额外的代码行。
答案 0 :(得分:365)
python -m pdb -c continue myscript.py
如果你没有提供-c continue
标志,那么你需要在执行开始时输入'c'(表示继续)。然后它将运行到错误点并让你控制那里。作为mentioned by eqzx,这个标志是python 3.2中的新增加,因此早期Python版本需要输入'c'(参见https://docs.python.org/3/library/pdb.html)。
答案 1 :(得分:107)
您可以使用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)
如果要使用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)
答案 2 :(得分:59)
使用以下模块:
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
。
答案 3 :(得分:36)
Ipython 有一个切换此行为的命令:%pdb 。它完全符合您的描述,甚至可能更多(通过语法突出显示和代码完成为您提供更多信息性回溯)。这绝对值得一试!
答案 4 :(得分:30)
这不是调试器,但可能同样有用(?)
我知道我听到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
你可以得到这个输出!
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
>>>
老实说,我没有用过这个,但我应该,似乎非常有用。
答案 5 :(得分:17)
IPython在命令行上使这个变得简单:
python myscript.py arg1 arg2
可以改写为
ipython --pdb myscript.py -- arg1 arg2
或者,类似地,如果调用模块:
python -m mymodule arg1 arg2
可以改写为
ipython --pdb -m mymodule -- arg1 arg2
注意--
阻止IPython将脚本的参数作为自己的参数。
这也有一个优点,就是调用增强的IPython调试器(ipdb)而不是pdb。
答案 6 :(得分:6)
如果您正在使用IPython环境,您可以使用%debug,shell将带您回到带有ipdb环境的违规行以进行检查等。另一个选项如上所述是使用iPython magic%pdb这实际上也是如此。
答案 7 :(得分:4)
答案 8 :(得分:4)
如果您使用的是ipython
,请在启动后输入%pdb
In [1]: %pdb
Automatic pdb calling has been turned ON
答案 9 :(得分:3)
要让它在开始时无需输入c即可运行:
python -m pdb -c c <script name>
Pdb有自己的命令行参数:-c c将在执行开始时执行c(ontinue)命令,程序将不间断地运行直到出错。
答案 10 :(得分:2)
答案 11 :(得分:0)
在层次结构中最顶层异常类的构造函数中放置一个断点,并且大多数时候您将看到引发错误的位置。
设置断点意味着您想要的意思:您可以使用IDE,或pdb.set_trace
,或其他
答案 12 :(得分:0)
如果您正在运行模块:
python -m mymodule
现在您想在发生异常时输入pdb
,请执行以下操作:
PYTHONPATH="." python -m pdb -c c mymodule/__main__.py
(或扩展您的PYTHONPATH
)。由于您现在正在运行PYTHONPATH
模块,因此需要pdb
以便在路径中找到模块。
答案 13 :(得分:0)
ipdb
有一个很好的上下文管理器来实现这种行为,使意图在语义上更清晰:
from ipdb import launch_ipdb_on_exception
with launch_ipdb_on_exception():
...