返回异常而不是投掷

时间:2014-03-20 14:52:27

标签: python error-handling monads

我有一组调用函数(下例中的bar()),当引发异常时(与Celery并行运行任务)表现不佳。因此,我更愿意捕获所有异常,然后返回它们。我的下面的代码演示了所需的行为,但是,我发现它相当冗长和细腻。有没有更好的选择可以模拟这种行为?性能不是问题。

class V():
    def __init__(self, x):
        self.value = x

class E():
    def __init__(self, e):
        self.error = e

def foo(a,b,c):
    try:
        return V(error_prone_function(a,b,c))
    except Exception as e:
        return E(e)

def bar():
    result = foo(1,2,3)
    if isinstance(result, V):
        do_success(result.value)
    else:
        do_failure(result.error)
编辑:我希望有一个foo()的通用版本。类似的东西:

def bar():
    result, error = foo(error_prone_function(a,b,c))
    if result:
        do_success(result)
    else:
        do_failure(error)

2 个答案:

答案 0 :(得分:1)

您还可以返回异常和实际值。 Python允许返回多个值。您可以使用结果的第一个值和错误的第二个值。 如果没有错误,那就是成功:

def foo(a,b,c):
    try:
        return error_prone_function(a,b,c), None
    except Exception as e:
        return None, e

def bar():
    result, error = foo(1,2,3)
    # did an error happen
    if error is None:
        do_failure(error)
    else:
        do_success(result)

以下是此解决方案的装饰器

def catchall(f):
    def func(*args, **kwargs):
        try:
            return f(*args, **kwargs), None
        except Exception as e:
            return None, e
    return func

然后你可以打电话

def bar():
    result, error = catchall(foo)(1,2,3)
    # did an error happen
    if error is None:
        do_failure(error)
    else:
        do_success(result)

答案 1 :(得分:1)

您可以使用装饰器功能:

def catchall(f):
    def func(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except Exception as e:
            return e
    return func

现在,这可以用于你所有的" dodgy"功能:

@catchall
def error_prone_function(...):

并在别处抓到:

result = error_prone_function(...)
if isinstance(result, Exception):
    # deal with failure
else:
    # success!

但是,处理特定错误通常比一般情况更好"出现问题&#34 ;;你应该弄清楚每个例程失败的原因并安装本地化的错误处理来管理它。