8.1 异常
- 异常:是某个类的实例;
- 大多数异常是 Exception 的子类,SystemExit、KeyboardInterrupt 等例外,这些异常由BaseException 派生而来;
BaseException 是 Exception 的超类;
- 自定义的异常必须是 Exception 的子类;
- 异常对象未被捕获时,程序终止并显示一条 traceback (错误信息);
8.2 让事情沿你指定的轨道出错
8.2.1 raise 语句
>>> raise Exception
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Exception
>>> raise Exception('hyperdive overload')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Exception: hyperdive overload
8.2.2 自定义异常类
- 自定义的异常类必须是 Exception 的子类;
- 定义方法与常规的类定义相同;
>>> class SomeCustomException(Exception):
... pass
>>> raise SomeCustomException()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.SomeCustomException
8.3 捕获异常
>>> try:
... x = int(input('Enter the first number: '))
... y = int(input('Enter the second number: '))
... print(x/y)
>>> except ZeroDivisionError:
... print("The second number can't be zero!")
8.3.1 不用提供参数
- 捕获异常后,可调用 raise ,且不提供任何参数(也可显式提供捕获到的异常),用于重新引发该异常(即继续向上传播);
- 若无法处理异常,可在 except 子句中使用不带参数的 raise 子句;
>>> class MuffledCalculator:
... muffled = False
... def calc(self, expr):
... try:
... return eval(expr)
... except ZeroDivisionError:
... if self.muffled:
... print('Division by zero is illegal')
... else:
... raise
>>> try:
... 1/0
... except ZeroDivisionError:
... raise ValueError
>>> try:
... 1/0
... except ZeroDivisionError:
... raise ValueError from None
8.3.2 多个 except 子句
>>> try:
... x = int(input('Enter the first number: '))
... y = int(input('Enter the second number: '))
... print(x/y)
... except ZeroDivisionError:
... print("The second number can't be zero!")
... except ValueError:
... print("That wasn't a number, was it?")
8.3.3 一个 except 子句捕获多种异常
>>> try:
... x = int(input('Enter the first number: '))
... y = int(input('Enter the second number: '))
... print(x/y)
... except (ZeroDivisionError, TypeError, NameError):
... print("Your numbers were bogus ...")
8.3.4 捕获对象
>>> try:
... x = int(input('Enter the first number: '))
... y = int(input('Enter the second number: '))
... print(x/y)
... except (ZeroDivisionError, ValueError, NameError) as e:
... print(e)
8.3.5 捕获所有异常
>>> except:
>>> except Exception as e:
8.3.6 循环输入直至满足要求
>>> while True:
... try:
... x = int(input('Enter the first number: '))
... y = int(input('Enter the second number: '))
... value = x/y
... print('x / y is', value)
... except:
... print('Invalid input. Please try again.')
... else:
... break
- 本方案的缺陷:except 子句只能捕获 Exception 及其子类的异常;
- except Exception as e:
该语句打印更具有提示性的错误信息;
8.3.7 finally 子句
>>> x = None
>>> try:
... x = 1/0
... finally:
... print('Clean up ...')
... del x
- 初始化 x 的原因:
若不初始化 x ,则出现异常后,ZeroDivisionError 没有机会对 x 赋值,在 finally 子句中执行 del 操作时引发未捕获的异常;
8.4 异常与函数-None
8.5 异常之禅-None
8.6 warn 与 filterwarnings,警告与抑制警告
>>> from warnings import warn
>>> warn("I've got a bad feeling about this.")
>>> from warnings import filterwarnings
>>> filterwarnings("ignore")
>>> warn("Anyone out there")
>>> filterwarnings("error")
>>> warn("Something is very wrong!")