2017-06-04 105 views
1

我想要一个Exception类,它在抛出时“有所作为”。 假例如:预抛钩自定义异常?

class BrowserEatRamError(Exception): 
    def __raise__(self): 
     os.system('Killall -9 chrome') 
     super(BrowserEatRamError, self).__raise__() 

当我把它用:

raise BrowserEatRamError('Chrome is eating all ram') 

抛出异常之前,Chrome应该会被关闭。有没有可以实现它的魔法?如果不是,实现类似行为的最优雅方式是什么?

编辑:

我不喜欢使用初始化因为初始化即使例外是一个尝试缓存中提出的将被调用。

+0

您是否尝试过在您的子类中的__init __()方法中执行此操作? – martineau

回答

2

没有这样的特殊方法存在。所有这些都记录在Data model

假设你使用的创建和初始化错误,然后养育孩子的(比较好)的做法,即

raise Error(args) 

代替:

err = Error(args) 
# Somewhere else 
raise err 

你可以简单地重载__intit__方法(被调用来初始化它)。

你也可以试试/除了。如果你经常这样做,你可以使用上下文管理器。

try: 
    # ... 
except Exception as e: 
    # Reraise if the exception doesn't have a `.on_raise()` method 
    # Or that method returns a falsey value. 
    if not hasattr(e, 'on_raise') or not e.on_raise(): 
     raise 
class CustomRaiseAction(object): 
    def __enter__(self): 
     return 
    def __exit__(exception_type, exception_value, traceback): 
     if hasattr(exception_type, 'on_raise'): 
      return exception_type.on_raise(exception_value) 
custom_raise_action = CustomRaiseAction() 

with custom_raise_action: 
    # ... 

在这两种方式,如果on_raise方法返回True,异常就会停止propogating。如果它返回False(或其他有错误的值,如None),它将被进一步抛出。

您也可以在没有上下文管理器的情况下通过覆盖sys.excepthook来做到这一点。这就像整个程序的__exit__一样,当程序即将结束时调用,默认情况下显示错误。请注意,如果另一个程序覆盖它,这将不起作用,并适用于所有情况,包括其他模块,这可能会导致意外的行为。

import sys 

old_excepthook = sys.excepthook 
def new_excepthook(exception_type, exception_value, traceback): 
    if hasattr(exception_type, 'on_raise'): 
     exception_type.on_raise(exception_value) 
    old_excepthook(exception_type, exception_value, traceback) 
sys.excepthook = new_excepthook 

而且,您不能停止异常并继续。

+0

即使在尝试缓存中引发异常,也会调用__init__。 CustomRaiseAction强制我的异常类的用户违反“干”。重写sys.excepthook似乎是最好的主意。 我认为“isinstance(exception_value,MyException)”会比“hasattr(exception_type,'on_raise')更好的检查 ” –