“外包”异常处理给装饰者

时间:2012-03-10 14:01:41

标签: python exception-handling decorator python-2.6

许多try / except / finally-clause不仅“uglify”我的代码,而且我发现自己经常对类似的任务使用相同的异常处理。因此,我正在考虑通过将它们“外包”给装饰者来减少冗余。

因为我肯定不是第一个得出这个结论的人,所以我用Google搜索并发现了这个 - imho - 巧妙recipe,它增加了处理多个例外的可能性。

但令我感到惊讶的是,为什么这似乎不是一个广为人知的习惯本身,所以我想知道是否有一个方面我没有考虑?

  1. 使用装饰器模式进行异常处理是假的还是我一直都想念它?请赐教!有什么陷阱?

  2. 是否有一个包/模块支持以合理的方式创建此类异常处理?

3 个答案:

答案 0 :(得分:25)

在代码本身中保留try / except / finally块的最大原因是错误恢复通常是函数的一个组成部分。

例如,如果我们有自己的int()函数:

def MyInt(text):
    return int(text)

如果text无法转换,我们该怎么办?返回0?返回None

如果你有很多简单的案例,那么我可以看到一个简单的装饰器是有用的,但我认为你链接的配方试图做太多:它允许为每个可能的异常激活不同的功能 - 在这种情况下作为那些(几个不同的例外,几个不同的代码路径)我会推荐一个专用的包装函数。

这是我对简单装饰器方法的看法:

class ConvertExceptions(object):

    func = None

    def __init__(self, exceptions, replacement=None):
        self.exceptions = exceptions
        self.replacement = replacement

    def __call__(self, *args, **kwargs):
        if self.func is None:
            self.func = args[0]
            return self
        try:
            return self.func(*args, **kwargs)
        except self.exceptions:
            return self.replacement

和样本用法:

@ConvertExceptions(ValueError, 0)
def my_int(value):
    return int(value)

print my_int('34')      # prints 34
print my_int('one')     # prints 0

答案 1 :(得分:5)

基本上,缺点是你不再决定如何在调用上下文中处理异常(只是让异常传播)。在某些情况下,这可能导致责任分离不足。

答案 2 :(得分:-1)

  1. Python中的装饰器与装饰器模式不同,认为有一些相似之处。你在这里的意思并不完全清楚,但我认为你的意思是Python中的那个(因此,最好不要使用模式这个词)

  2. Python中的装饰器对异常处理没有用,因为你需要将一些上下文传递给装饰器。也就是说,你要么传递一个全局上下文,要么在某些外部上下文中隐藏函数定义,这就要求我说LISP式的思维方式。

  3. 您可以使用上下文管理器代替装饰器。我确实将它们用于此目的。