2017-06-04 100 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')更好的檢查 」 –