是否可以将异常处理推迟到Python中的一个类的单个函数?

时间:2014-08-13 18:53:43

标签: python class exception exception-handling

我正在用Python编写一个类,部分代码处理服务器。因此,我需要处理像ExpiredSession或ConnectionError这样的异常。

我没有为每个try / except块编写异常处理代码,而是在类中有一个函数来处理异常。像这样的东西(在类定义中)

def job_a(self):
    try:
        do something
    except Exception as e:
        #maybe print the error on screen.
        self.exception_handling(e)

def job_b(self):
    try:
        do something else
    except Exception as e:
        #maybe print the error on screen.
        self.exception_handling(e)


def exception_handling(self,e):
    if isInstanceOf(e,ExpiredSession):
        #deal with expired session.
        self.reconnect()
    if isInstanceOf(e,ConnectionError):
        #deal with connection error
    else:
        #other exceptions

我不确定这种代码是否会导致任何问题,因为我没有看到代码这样做。比如,可能的内存泄漏? (现在我注意到当我有越来越多的错误/异常时,内存使用量会增长(虽然很慢),最终我必须重新启动进程才能吃掉所有的回忆。不确定这是原因。

将异常传递给单个函数是一种好习惯吗?

1 个答案:

答案 0 :(得分:3)

这是context manager的一个很好的用例。您可以看到一些使用上下文管理器进行错误处理的示例herecontextmanager装饰器允许您以单个函数的形式简明地编写上下文管理器。这是一个简单的例子:

class Foo(object):
    def meth1(self):
        with self.errorHandler():
            1/0

    def meth2(self):
        with self.errorHandler():
            2 + ""

    def meth3(self):
        with self.errorHandler():
            # an unhandled ("unexpected") kind of exception
            ""[3]

    @contextlib.contextmanager
    def errorHandler(self):
        try:
            yield
        except TypeError:
            print "A TypeError occurred"
        except ZeroDivisionError:
            print "Divide by zero occurred"

然后:

>>> x = Foo()
>>> x.meth1()
Divide by zero occurred
>>> x.meth2()
A TypeError occurred

with语句允许您"卸载"错误处理到一个单独的函数中,您可以捕获异常并使用它们执行您喜欢的操作。在你的真实"函数(即执行工作但可能引发异常的函数),只需要with语句而不是整个复杂的try / except语句块。

这种方法的另一个优点是,如果出现无法预料的异常,它将正常传播而无需额外的努力:

>>> x.meth3()
Traceback (most recent call last):
  File "<pyshell#394>", line 1, in <module>
    x.meth3()
  File "<pyshell#389>", line 12, in meth3
    ""[3]
IndexError: string index out of range

另一方面,在您提出的解决方案中,异常已经在每个函数中捕获,并且实际的异常对象被传递给处理程序。如果处理程序出现意外错误,则必须手动重新加载它(并且甚至不能使用裸raise来执行此操作)。使用上下文管理器,意外的异常具有普通行为,无需额外的工作。