在Python中创建一个自定义异常类时,常常遇到这样的问题:如何让这些异常类在派生类中可被继承?
例如,我们创建一个基类BaseClass
,并在其中定义两个异常类SomeError
和OtherError
。然后,我们创建一个派生类DerivedClass
,并希望在其中使用这两个异常类。
下面是具体代码:
# baseclass.py
class Error(Exception):
"""Base class for exceptions in BaseClass"""
pass
class SomeError(Error):
"""Exception for some error"""
def __init__(self, msg):
self.msg = msg
class OtherError(Error):
"""Exception for some error"""
def __init__(self, msg):
self.msg = msg
class BaseClass():
"""Base test class for testing exceptions"""
def dosomething(self):
raise SomeError, "Got an error doing something"
# derivedclass.py
from baseclass import BaseClass, SomeError, OtherError
class DerivedClass(BaseClass):
def doother(self):
"""Do other thing"""
raise OtherError, "Error doing other"
# test.py
from derivedclass import DerivedClass, SomeError, OtherError
"""Test from within module"""
x = DerivedClass()
try:
x.dosomething()
except SomeError:
print "I got some error ok"
try:
x.doother()
except OtherError:
print "I got other error ok"
按照上面的代码,我们可以看到,为了让派生类DerivedClass
可以使用基类BaseClass
中的异常类SomeError
和OtherError
,我们需要在DerivedClass
中导入这两个异常类。
这种方法虽然可以实现我们的目的,但并不优雅,并且容易出错。如果我们忘记在派生类中导入异常类,就会导致派生类无法使用这些异常类,从而导致程序出错。
2、解决方案
为了解决这个问题,我们可以使用six
库中的reraise
函数。reraise
函数可以将一个异常从一个函数重新抛出到另一个函数。
下面是具体代码:
# baseclass.py
class Error(Exception):
"""Base class for exceptions in BaseClass"""
pass
class SomeError(Error):
"""Exception for some error"""
def __init__(self, msg):
self.msg = msg
class OtherError(Error):
"""Exception for some error"""
def __init__(self, msg):
self.msg = msg
class BaseClass():
"""Base test class for testing exceptions"""
def dosomething(self):
raise SomeError, "Got an error doing something"
# derivedclass.py
from baseclass import BaseClass, Error
class DerivedClass(BaseClass):
def doother(self):
"""Do other thing"""
try:
raise OtherError, "Error doing other"
except Error:
six.reraise(*sys.exc_info())
# test.py
from derivedclass import DerivedClass, SomeError, OtherError
"""Test from within module"""
x = DerivedClass()
try:
x.dosomething()
except SomeError:
print "I got some error ok"
try:
x.doother()
except OtherError:
print "I got other error ok"
在上面的代码中,我们在DerivedClass
的doother
方法中使用six.reraise
函数将OtherError
异常重新抛出到BaseClass
的dosomething
方法。
这样,我们就可以让派生类DerivedClass
使用基类BaseClass
中的异常类SomeError
和OtherError
,而不需要在派生类中导入这两个异常类。
这种方法更加优雅,并且不容易出错。即使我们忘记在派生类中导入异常类,派生类仍然可以使用这些异常类。