6-3-异常对象
2020年12月20日大约 3 分钟
基于类的异常有如下特点:
- 提供类型分类,对今后的修改有更好的支持。
- 它们附加了状态信息。
- 它们支持继承。
1. 异常:回到未来
1.1 编写异常类
class General(Exception): pass
class Specific1(General): pass
class Specific2(General): pass
def raiser0():
X = General()
raise X
def raiser1():
X = Specific1()
raise X
def raiser2():
X = Specific2()
raise X
for func in (raiser0, raiser1, raiser2):
try:
func()
except General:
import sys
print('caught:', sys.exc_info()[0])
caught: <class '__main__.General'>
caught: <class '__main__.Specific1'>
caught: <class '__main__.Specific2'>
2. 为什么使用类异常
把库的异常安排到类树中,有个共同的超类来包装整个类型。这样,用户只需列出共同的超类,来捕捉库的所有异常。
3. 内置 Exception 类
Python 把内置异常组织成层次,来支持各种捕捉模式。
**BaseException。**异常的顶级根类。这个类不能当作是由用户定义的类直接继承的(使用 Exception)。它提供了子类所继承的默认的打印和状态保持行为。
**Exception。**与应用相关的异常的顶层根超类。是所有其他内置异常的超类,除了系统推出事件类之外。
**ArithmeticError。**所有数值错误的超类。
**OverflowError。**识别特定的数值错误的子类。
3.1 默认打印和状态
内置异常还提供了默认打印显示和状态保持。传递给这些类的任何构造函数参数都会保存在实例的 args 元组属性中,并且当打印该实例的时候自动显示,对于用户定义的异常也是如此:
raise IndexError
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-3-55a00e7db5b5> in <module>()
----> 1 raise IndexError
IndexError:
raise IndexError('spam')
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-4-53b7e456dbfa> in <module>()
----> 1 raise IndexError('spam')
IndexError: spam
I = IndexError('spam')
I.args
('spam',)
4. 定制打印显示
可以在类中定义两个字符串表示重载方法中的一个(__repr__
或 __str__
),来返回想要为异常显示的字符串:
class MyBad(Exception):
def __str__(self):
return 'Always look on the bright side of life...'
try:
raise MyBad()
except MyBad as X:
print(X)
Always look on the bright side of life...
raise MyBad()
---------------------------------------------------------------------------
MyBad Traceback (most recent call last)
<ipython-input-7-ff3b7d17d944> in <module>()
----> 1 raise MyBad()
MyBad: Always look on the bright side of life...
5. 定制数据和行为
5.1 提供异常细节
当引发一个异常的时候,可能会跨越任意的文件界限——触发异常的 raise 语句和捕获异常的 try 语句可能位于完全不同的模块文件中。在异常自身中传递额外的状态信息,这允许 try 语句更可靠地访问它。
class FormatError(Exception):
def __init__(self, line, file):
self.line = line
self.file = file
def parser():
raise FormatError(42, file='spam.txt')
try:
parser()
except FormatError as X:
print('Error at', X.file, X.line)
Error at spam.txt 42
5.2 提供异常方法
异常类也可以定义在处理器中调用的方法:
# 使用异常状态信息把错误记录到一个文件中
class FormatError(Exception):
logfile = 'formaterror.txt'
def __init__(self, line, file):
self.line = line
self.file = file
def logerror(self):
log = open(self.logfile, 'a')
print('Error at:', self.file, self.line, file=log)
def parser():
raise FormatError(40, 'spam.txt')
if __name__ == '__main__':
try:
parser()
except FormatError as exc:
exc.logerror()