5

我正在用 Python 编写一个程序,几乎我的类中的每个方法都是这样编写的:

def someMethod(self):
    try:
       #...
    except someException:
       #in case of exception, do something here

       #e.g display a dialog box to inform the user 
       #that he has done something wrong

随着班级的增长,一遍又一遍地编写相同的 try-except 块有点烦人。是否可以为整个班级创建某种“全局”异常?Python中推荐的处理方法是什么?

4

2 回答 2

11

编写一个或多个异常处理函数,给定一个函数和其中引发的异常,执行您想要执行的操作(例如显示警报)。如果你需要不止一个,写出来。

def message(func, e):
    print "Exception", type(e).__name__, "in", func.__name__
    print str(e)

现在编写一个装饰器,将给定的处理程序应用于被调用的函数:

import functools

def handle_with(handler, *exceptions):
    try:
        handler, cleanup = handler
    except TypeError:
        cleanup = lambda f, e: None
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except exceptions or Exception as e:
                return handler(func, e)
            finally:
                cleanup(func, e)
        return wrapper
    return decorator

这仅捕获您指定的异常。如果您不指定任何内容,Exception则会被捕获。此外,第一个参数可以是两个处理函数的元组(或其他序列);finally第二个处理程序(如果给定)在子句中调用。从主处理程序返回的值作为函数调用的值返回。

现在,鉴于上述情况,您可以编写:

@handle_with(message, TypeError, ValueError)
def add(x, y):
    return x + y

您也可以使用上下文管理器执行此操作:

from contextlib import contextmanager 

@contextmanager
def handler(handler, *exceptions):
    try:
        handler, cleanup = handler
    except TypeError:
        cleanup = lambda e: None
    try:
        yield
    except exceptions or Exception as e:
        handler(e)
    finally:
        cleanup(e)

现在你可以写:

def message(e):
    print "Exception", type(e).__name__
    print str(e)

 def add(x, y):
     with handler(message, TypeError, ValueError):
         return x + y

请注意,上下文管理器不知道它在哪个函数中(你可以找到它,sorta, using inspect,虽然这是“魔法”,所以我没有这样做)所以它给你的信息不太有用。此外,上下文管理器不会让您有机会在处理程序中返回任何内容。

于 2013-10-07T19:36:38.797 回答
3

我可以想到两个选择:

  1. 编写一个可以将每个方法包装在try块中的装饰器。
  2. 编写一个“调度程序”方法,在try块内调用适当的方法,然后调用该方法而不是单独的方法。也就是说,不是调用obj.someMethod(), obj.otherMethod,而是调用obj.dispatch('someMethod')or obj.dispatch('otherMethod'),其中dispatch是包含try块的包装器。

不过,您的方法似乎有点奇怪。在代码的其他部分中包含对话框内容可能更有意义,一些更高级别的事件循环可以捕获错误并显示有关它们的消息。

于 2013-10-07T18:56:13.623 回答