问题很简单,看起来很通用。我将在一些操作期间收集所有错误并将所有错误显示给用户。
我的问题是:这种模式是否有任何常见的库实现?
考虑以下示例。我需要一组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)
所以,问题再次出现:
谢谢。
答案 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
这里有一个很大的缺陷,即装饰器定义了一个全局变量。它可能会失控,所以要小心使用它!