无法覆盖 sys.excepthook
我尝试按照这个方法来定制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。