这个问题我想了很久,但一直没有找到合适的解决方案。如果我运行一个脚本,遇到一个IndexError, python会打印出错误的行、位置和快速描述,然后退出。是否有可能在遇到错误时自动启动pdb ?我并不反对在文件顶部添加额外的import语句,也不反对添加几行额外的代码。


当前回答

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的优点。

其他回答

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的优点。

使用以下模块:

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路径中的某个地方。

现在,在脚本的开头,只需添加一个导入调试。

Ipdb有一个很好的上下文管理器来实现这种行为,这使得意图在语义上更清晰:

from ipdb import launch_ipdb_on_exception

with launch_ipdb_on_exception():
    ...

如果您正在使用IPython环境,您可以只使用%debug, shell将带您回到ipdb环境中的违规行进行检查等。上面提到的另一个选项是使用iPython magic %pdb,它可以有效地完成同样的工作。

从3.7开始,你可以在你的代码中直接使用关键字breakpoint(不需要任何导入),就像这样:

try:
    ...  # The line that raises an error
except:
    breakpoint()