2011-03-21 20 views
11

在python中處理異常時,我發現自己經常重複代碼。基本模式是這樣的形式:什麼是一些優雅的方法來在python中抽象出重複的異常處理?

try: 
    action_here() 
except CommonException1: 
    Action_always_taken_for_CommonException1() 
except CommonException2: 
    Action_always_taken_for_CommonException2() 
except Exception: 
    Default_action_always_taken() 

我想要做的是一些如何抽象這個重複的代碼到一個函數或類。我知道這樣做的一種方法是調用一個異常處理函數與異常對象,如:

try: 
    action_here() 
except Exception as e: 
    handle_exception(e) 

然後在這個函數確定基於類的例外。

def handle_exception(e): 
    if type(e) == type(CommonException1()): 
    Action_always_taken_for_CommonException1() 
    elif type(e) == type(CommonException2()): 
    Action_always_taken_for_CommonException2()) 
    else: 
    Default_action_always_taken() 

但是,這感覺笨重和不雅。所以我的問題是,處理重複異常處理的其他選擇是什麼?

+0

這看起來像它可以得到的優雅。你想用什麼? – Blender 2011-03-21 06:24:09

+0

@Blender我的解決方案是我想出的唯一可行的解​​決方案。我正在詢問是否有人知道更好的解決方案。 – cledoux 2011-03-21 17:40:07

回答

19

這種情況的主要用例情境的經理之一,with語句:

from __future__ import with_statement # Needed in 2.5, but not in 2.6 or later 

from contextlib import contextmanager 

@contextmanager 
def handle_exceptions(): 
    try: 
     yield # Body of the with statement effectively runs here 
    except CommonException1: 
     Action_always_taken_for_CommonException1() 
    except CommonException2: 
     Action_always_taken_for_CommonException2() 
    except Exception: 
     Default_action_always_taken() 

# Used as follows 
with handle_exceptions(): 
    action_here() 
+0

這正是我尋找的東西的類型。謝謝! – cledoux 2011-03-21 17:42:38

6

如果你不喜歡重複if/elseif塊,你可以把你的手柄在一個字典,按類型鍵:

handlers = { type(CommonException1()) : Action_always_taken_forCommonException1, 
      type(CommonException2()) : Action_always_taken_forCommonException2 } 

def handle_exception(te): 
    if te in handlers: 
    handlers[te]() 
    else: 
    Default_action() 

然後你可以用運行:

try: 
    action_here() 
except Exception as e: 
    handle_exception(type(e)) 

另外:如果您發現自己經常編寫這些try塊,那麼您可以編寫自己的上下文管理器(se e here)。在action_here()側,您的代碼會再看看這樣的:

with my_error_handling_context(): 
    action_here1() 
    action_here2() 

在這種情況下,handle_exception代碼將基本上是你的上下文管理器的__exit__方法(這將永遠獲得通過在同塊中引發任何異常)。

+0

上下文管理器正是我正在尋找的解決方案類型。謝謝! – cledoux 2011-03-21 17:45:08

5

儘管使用(與建議他人)上下文管理的解決方案是最優雅的,而且會是什麼我也會推薦,我想指出你的handle_exception函數可以通過重新提升例外來更優雅地編寫:

def handle_exception(e): 
    try: 
    raise e 
    except CommonException1: 
    Action_always_taken_for_CommonException1() 
    except CommonException2: 
    Action_always_taken_for_CommonException2() 
    except Exception: 
    Default_action_always_taken() 
+0

謝謝,我從來不會想到這一點。 – cledoux 2011-03-21 17:46:02

相關問題