Monkey Patching Exception类和其他内置类

时间:2014-03-05 02:20:46

标签: python

无论Excpetion类型如何,我都希望在发生异常时打印一条消息。

我尝试了以下内容:

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 个答案:

答案 0 :(得分:6)

为什么不进行猴子补丁?

让我解释为什么预计的方法存在缺陷。将MyException分配给Exception时会发生的情况是您更改了此模块中的全局变量Exception。在此分配之前或在不同模块中定义的所有异常类都不会使用它。他们将使用原始值。由于IOError是在解释器启动期间创建的,因此您的分配对其没有影响。因此,如果您要修补Exception类,那么您将覆盖其方法。最重要的是,您将更改其__init____new__方法。不幸的是,不支持该方法,并且更改这些属性会导致:

TypeError: can't set attributes of built-in/extension type 'exceptions.Exception'

因此修补解释器的方法可能无法解决。

替代方案:追踪

另一种方法是编写一个要传递给sys.settrace的函数。它为每个函数调用调用,如果要跟踪特定调用,则应返回另一个跟踪函数。各种事件被传递给后一个跟踪函数,其中一个是'exception'。通过过滤这些事件,您可能已经达到了预期的效果。