2014-04-22 38 views
4

我有一個通用函數,用於嚮應用程序日誌發送有關異常的信息。 我使用類的方法中的exception_handler函數。傳入exception_handler並由exception_handler調用的應用程序日誌處理程序會創建一個JSON字符串,該字符串實際上會被髮送到日誌文件。這一切工作正常。在try /使用裝飾器除外包裝類方法

def exception_handler(log, terminate=False): 
    exc_type, exc_value, exc_tb = sys.exc_info() 
    filename, line_num, func_name, text = traceback.extract_tb(exc_tb)[-1] 
    log.error('{0} Thrown from module: {1} in {2} at line: {3} ({4})'.format(exc_value, filename, func_name, line_num, text)) 
    del (filename, line_num, func_name, text) 
    if terminate: 
     sys.exit() 

我使用它作爲如下:(a超簡化的示例)

from utils import exception_handler 

class Demo1(object): 
    def __init__(self): 
     self.log = {a class that implements the application log} 

    def demo(self, name): 
     try: 
      print(name) 
     except Exception: 
      exception_handler(self.log, True) 

我想改變exception_handler用作裝飾爲大量的方法,即:

@handle_exceptions 
def func1(self, name) 
    {some code that gets wrapped in a try/except by the decorator} 

我看過很多關於裝飾器的文章,但我還沒有想出如何實現我想要做的事情。我需要傳遞對活動日誌對象的引用,並將0個或更多參數傳遞給包裝函數。我很樂意將exception_handler轉換爲類中的方法,如果這樣做更容易。

回答

8

這樣的裝飾,簡直是:

def handle_exceptions(f): 
    def wrapper(*args, **kw): 
     try: 
      return f(*args, **kw) 
     except Exception: 
      self = args[0] 
      exception_handler(self.log, True) 
    return wrapper 

這個裝飾簡單地調用try套房裏麪包裝的函數。

這隻適用於方法,因爲它假定第一個參數是self

+0

感謝馬亭。這看起來不錯,但我如何將self.log傳入handle_exceptions?沒有「自我」可見。 – RoyHB

+0

@RoyHB:啊,我錯過了你在那裏使用了'self.log',我的歉意。調整爲使用'args [0]',但是你也可以用'def wrapper(self,* args,** kw)'使'wrapper()'得到一個明確的'self'參數,並使用'return f(self ,* args,** kw)'。 –

+0

不應該在底部有一個'返回包裝器'? –

0

感謝Martijn指引我朝着正確的方向前進。 我不能讓他的建議的解決方案的工作,但更多的是一些搜索基於他的榜樣後,下面的工作正常:

def handle_exceptions(fn): 
    from functools import wraps 
    @wraps(fn) 
    def wrapper(self, *args, **kw): 
     try: 
      return fn(self, *args, **kw) 
     except Exception: 
      exception_handler(self.log) 
    return wrapper