如何在Python中全局设置sys.excepthook以调用pdb?

7 投票
3 回答
5954 浏览
提问于 2025-04-15 13:25

来自Python文档:

sys.excepthook(type, value, traceback)

这个函数会把出现的错误信息和错误追踪打印到 sys.stderr,也就是错误输出的地方。

当程序中出现了一个错误但没有被处理时,解释器会调用 sys.excepthook,并传入三个参数:错误的类型、错误的实例和一个追踪对象。在交互式会话中,这个调用发生在控制权返回到提示符之前;在Python程序中,这个调用发生在程序即将退出之前。你可以通过把另一个接受三个参数的函数赋值给 sys.excepthook 来定制这种顶层错误的处理方式。

http://docs.python.org/library/sys.html

我该如何全局修改这个设置,让默认行为总是调用 pdb?有没有配置文件可以更改?我不想在我的代码中包裹这个。

3 个回答

0

试试这个:

import pdb
import sys

def excepthook(type, value, traceback):
    pdb.post_mortem(traceback)

excepthook.old = sys.excepthook
sys.excepthook = excepthook

def raise_exception():
    raise_exception()

raise_exception()
1

另一个选择是使用ipython,我认为这是每个Python开发者都应该拥有的工具。与其从命令行运行你的脚本,不如在ipython中用%run来运行。当出现错误时,你可以输入%debug来调试它。(还有一个选项可以自动调试任何发生的错误,但我忘了是什么了。)

22

你需要了解的内容如下

http://ynniv.com/blog/2007/11/debugging-python.html

有三种方法,第一种简单但比较粗糙(Thomas Heller提供的) - 你可以在site-packages/sitecustomize.py文件中添加以下内容:

import pdb, sys, traceback
def info(type, value, tb):
    traceback.print_exception(type, value, tb)
    pdb.pm()
sys.excepthook = info

第二种方法更复杂一些,它会检查是否处于交互模式(有点奇怪的是,它会跳过交互模式下的调试),这个方法来自于食谱

# 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

第三种方法(无论stdin或stderr是否被重定向,都会启动调试器)是由ynniv提供的:

# code snippet, to be included in 'sitecustomize.py'
import sys

def info(type, value, tb):
   if (#hasattr(sys, "ps1") or
       not sys.stderr.isatty() or 
       not sys.stdin.isatty()):
       # stdin or stderr is redirected, just do the normal thing
       original_hook(type, value, tb)
   else:
       # a terminal is attached and stderr is not redirected, debug 
       import traceback, pdb
       traceback.print_exception(type, value, tb)
       print
       pdb.pm()
       #traceback.print_stack()

original_hook = sys.excepthook
if sys.excepthook == sys.__excepthook__:
    # if someone already patched excepthook, let them win
    sys.excepthook = info

撰写回答