猴子补丁异常类和其他内建类
无论是什么类型的错误,我都想在发生错误时打印一条消息。
我试过以下代码:
class MyException(BaseException):
def __init__(self, msg):
super(BaseException, self).__init__(msg)
print "Howdy", msg
__builtins__.Exception = MyException
try:
raise IOError("world")
except Exception as e:
pass
我本来期待能看到“Howdy world”这句话被打印出来,但结果什么都没有。
补充说明:
@helmut 建议使用 sys.settrace,这段代码按预期工作。
import sys
def trace(frame, event, arg):
print event
return trace
sys.settrace(trace)
def foo():
raise Exception()
def bar():
foo()
def baz():
try:
bar()
except:
pass
baz()
exit()
可惜这对我的情况来说太慢了。
1 个回答
6
为什么不使用猴子补丁?
让我来解释一下这个方法的问题。你把 MyException
赋值给 Exception
的时候,其实是改变了这个模块里的全局变量 Exception
。在这个赋值之前定义的所有异常类,或者在其他模块里的异常类,都不会使用这个新的值,它们还是会用原来的那个值。因为 IOError
是在解释器启动时创建的,所以你的赋值对它没有影响。所以如果你试图用猴子补丁的方式去修改 Exception
类,你实际上是在覆盖它的方法。最重要的是,你会改变它的 __init__
和 __new__
方法。可惜的是,这个方法是不被支持的,改变这些属性会导致:
TypeError: can't set attributes of built-in/extension type 'exceptions.Exception'
所以用猴子补丁的方式来修改解释器可能不会成功。
替代方案:追踪
一个替代的方法是写一个函数,然后把它传给 sys.settrace
。这个函数会在每次调用其他函数时被调用,如果某个特定的调用需要被追踪,它应该返回另一个追踪函数。各种事件会被传递给这个追踪函数,其中一个事件是 'exception'
。通过过滤这些事件,你可能就能达到你想要的效果。