收集所有错误并提高减少的异常

时间:2015-03-19 16:33:48

标签: python

问题很简单,看起来很通用。我将在一些操作期间收集所有错误并将所有错误显示给用户。

我的问题是:这种模式是否有任何常见的库实现?

考虑以下示例。我需要一组MyClass对象。创建此对象可能会失败,因此示例代码可能如下所示:

class MyError(Exception):
    pass


class MyClass:
    def __init__(self, foo, bar):
        if foo % 2 == 0:
            raise MyError('Unable to create object with foo={}, bar={}'.format(
                foo, bar))

        self.foo = foo

第一个例子将在第一个例外失败,这不是我需要的:

def fail_on_first():
    try:
        return [MyClass(i, None) for i in range(10)]
    except MyError as e:
        raise

下一个代码具有所需的行为:

def collect_all_errors():
    errors = []
    objects = []

    for i in range(10):
        try:
            objects.append(MyClass(i, None))
        except MyError as e:
            errors.append(e)

    if errors:
        raise MyError('\n'.join(e.message for e in errors))

    return objects

但这不够普遍。让我们试着概括一下:

class Args:
    def __init__(self, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs


def collect_all_errors_generalized(exception_type, callable, argslist):
    errors = []
    objects = []

    for args in argslist:
        try:
            objects.append(callable(*args.args, **args.kwargs))
        except exception_type as e:
            errors.append(e)

    if errors:
        raise exception_type('\n'.join(e.message for e in errors))

    return objects

申请代码是:

try:
    objects = collect_all_errors_generalized(
        MyError, MyClass, [Args(i, 'bar') for i in range(10)])
except MyError as e:
    print(e)

或没有args:

def collect_all_errors_generalized_lambdas(exception_type, callables):
    errors = []
    objects = []

    for callable in callables:
        try:
            objects.append(callable())
        except exception_type as e:
            errors.append(e)

    if errors:
        raise exception_type('\n'.join(e.message for e in errors))

    return objects

def create_factory(mytype, *args, **kwargs):
    return lambda: mytype(*args, **kwargs)

try:
    collect_all_errors_generalized_lambdas(
        MyError, [create_factory(MyClass, i, 'bar')
                  for i in range(10)])
except MyError as e:
    print(e)

所以,问题再次出现:

  1. 这是常见的模式吗?
  2. 它是否有任何良好的实现或有用的片段?
  3. 谢谢。

1 个答案:

答案 0 :(得分:0)

首先,我不知道为什么你认为这应该是一个好主意。

关于问题:

1:不,这不是常见的模式。例外最常用于处理代码问题,有时用于控制流程。

2:既然这不是一个好主意,我认为这不是一个好的实现,甚至是一个有用的片段,无论如何...

这是"泛型"装饰器,您可以作为要记录exception的参数传递。

def exceptloger(exceptions=None):
    def wrapper(func):
        def func_wrapper(*args, **kwargs):
            if 'excepts' not in globals():
                global excepts
                excepts = []
            try:
                return func(*args, **kwargs)
            except Exception as e:
                excpt = e.__class__.__name__
                if exceptions and excpt in exceptions:
                    excepts.append({excpt: e.message})
                if exceptions == 'all':
                    excepts.append({excpt: e.message})
        return func_wrapper
    return wrapper

装饰你想要处理的方法

class MyError(Exception):
    pass

class MyClass(object):
    def __init__(self, foo, bar):
        if not foo % 2:
            raise MyError('Unable to create object with foo={}, bar={}'.format(foo, bar))

@exceptloger('MyError')
def fail_on_first():
    results = []
    for i in range(10):
        results.append(MyClass(i, None))
    return results

@exceptloger('all')
def zerodivison():
    return 1 / 

结果

fail_on_first()
zerodivison()

print excepts

这里有一个很大的缺陷,即装饰器定义了一个全局变量。它可能会失控,所以要小心使用它!