2014-02-21 30 views
1

下面的例子僅僅是一個黑客,因爲我不知道更好它:如何收集幾個錯誤來提出這些總結?

class ErrorCollector(Exception): 
    def __init__(self): 
     self.errors = [] 

    def __nonzero__(self): 
     return bool(self.errors) 

def do_something(a, b): 
    err = ErrorCollector() 
    try: 
     int(a) 
    except Exception: 
     err.errors.append('{!r} fails'.format(a)) 
    try: 
     int(b) 
    except Exception: 
     err.errors.append('{!r} fails'.format(b)) 
    if err: 
     raise err 

def run(*args): 
    err = ErrorCollector() 
    for arg in args: 
     try: 
      do_something(*arg) 
     except Exception as e: 
      err.errors.extend(e.errors) 
    if err: 
     print 'You have these problems:\n{}'.format('\n'.join(err.errors)) 

我怎樣才能做得更好?我之前的解決方案是收集列表中的錯誤描述並將其傳遞給錯誤實例。因此,畢竟這與此處顯示的解決方案類似。

+0

我懷疑有一種方法可以做到這一點。你基本上想要運行代碼,儘管發生了異常,這似乎是不可能的,而且完全錯誤,因爲在定義變量的行期間發生異常之後,引用該變量的任何代碼都會引發NameError,並且您無法做到,而是手動處理默認值。 – teferi

回答

0

就是這樣的。

#!/usr/bin/env python 
import functools 
import inspect 
import sys 
import traceback 


class ErrorCollector(Exception): 
    def __init__(self): 
     self.errors = [] 

    def __enter__(self): 
     return self 

    def __exit__(self, exc_type, exc_val, exc_tb): 
     self.append(exc_type, exc_val, exc_tb) 
     if self.errors: 
      raise self 

    def append(self, exc_type=None, exc_val=None, exc_tb=None): 
     if exc_type is None and exc_val is None and exc_tb is None: 
      exc_type, exc_val, exc_tb = sys.exc_info() 
     if exc_type is not None and exc_val is not None and exc_tb is not None: 
      self.errors.append('\n'.join(traceback.format_exception(exc_type, exc_val, exc_tb))) 

    def __str__(self): 
     return '\n'.join(self.errors) 

    __unicode__ = __str__ 


def error_collector(func): 
    @functools.wraps(func) 
    def wrapper(*args, **kwargs): 
     with ErrorCollector() as err_collector: 
      names, _, _, _ = inspect.getargspec(func) 
      if 'err_collector' in names: 
       kwargs['err_collector'] = err_collector 
      return func(*args, **kwargs) 
    return wrapper 


def test1(): 
    with ErrorCollector(): 
     print 'no errors' 

    with ErrorCollector() as err_collector: 
     try: 
      raise Exception('1') 
     except: 
      err_collector.append() 
     raise Exception('2') 


@error_collector 
def test2(): 
    raise Exception('3') 


@error_collector 
def test3(err_collector): 
    try: 
     raise Exception('4') 
    except: 
     err_collector.append() 
    raise Exception('5') 


if __name__ == '__main__': 
    try: 
     test1() 
    except Exception as e: 
     print e 

    try: 
     test2() 
    except Exception as e: 
     print e 

    try: 
     test3() 
    except Exception as e: 
     print e