无法覆盖 sys.excepthook

11 投票
5 回答
5612 浏览
提问于 2025-04-15 13:32

我尝试按照这个方法来定制sys.excepthook的行为。

在ipython中:

:import pdb, sys, traceback
:def info(type, value, tb):
:    traceback.print_exception(type, value, tb)
:    pdb.pm()
:sys.excepthook = info
:--
>>> x[10] = 5
-------------------------------------------------
Traceback (most recent call last):
  File "<ipython console>", line 1, in <module>
NameError: name 'x' is not defined
>>>

发现pdb.pm()没有被调用。看起来在我的Python 2.5安装中,sys.excepthook = info并没有生效。

5 个回答

2

在Chris的回答基础上,你可以使用另一种功能,比如装饰器,来为Jupyter的showbacktrace添加你自己的功能:

from IPython.core.interactiveshell import InteractiveShell
from functools import wraps
import traceback
import sys

def change_function(func):
    @wraps(func)
    def showtraceback(*args, **kwargs):
        # extract exception type, value and traceback
        etype, evalue, tb = sys.exc_info()
        if issubclass(etype, Exception):
            print('caught an exception')
        else:
            # otherwise run the original hook
            value = func(*args, **kwargs)
            return value
    return showtraceback

InteractiveShell.showtraceback = change_function(InteractiveShell.showtraceback)

raise IOError
24

在你写下这个的五年后,IPython 仍然是这样工作的,所以我想这个解决方案可能对搜索这个问题的人有用。

每次你执行一行代码时,IPython 都会替换掉 sys.excepthook,所以你对它的修改没有任何效果。而且,IPython 甚至根本不调用 sys.excepthook,它会自己捕捉所有的错误并处理这些错误,根本不会让你修改的代码起作用。

如果你想在 IPython 运行时修改错误处理的方式,可以通过“猴子补丁”来修改它们的 shell 的 showtraceback 方法。比如,下面是我如何修改的,让它看起来像普通的 Python 错误追踪(因为我不喜欢 IPython 的错误信息太啰嗦):

def showtraceback(self, *args, **kwargs):
    traceback_lines = traceback.format_exception(*sys.exc_info())
    del traceback_lines[1]
    message = ''.join(traceback_lines)
    sys.stderr.write(message)

import sys
import traceback
import IPython
IPython.core.interactiveshell.InteractiveShell.showtraceback = showtraceback

这个方法在普通的终端控制台和 Qt 控制台中都能用。

14

你现在用的ipython是一个比普通Python交互式命令行更高级的工具,它会自己处理所有的错误,不会使用系统默认的错误处理方式(sys.excepthook)。如果你想让它在遇到未处理的错误时自动进入调试模式,可以用命令ipython -pdb来启动,而不是单纯地用ipython。这样一来,当出现错误时,它就会像你想用excepthook那样,自动调用调试工具pdb。

撰写回答