在Python中所有的异常类都是Exception的子类。Exception定义在exceptions模块中,该模块在Python的内建命名空间中,不必导入就可以直接使用。
访问未声明的变量会引发NameError异常。
当除数为0的时候会引发ZeroDivisionError异常。
当解释器发现语法错误,会引发SyntaxError异常。
当使用序列中不存在的索引时,会引发IndexError异常。
当使用映射中不存在的键时,会引发KeyError异常。
试图打开不存在文件时,会引发FileNotFoundError异常。
尝试访问未知的对象属性时,会引发AttributeError异常。
Python使用try-except语句处理异常,其中try语句检测异常,except语句用于捕获异常。
try-except语句格式:
try:
# 语句块
except :
# 异常处理代码
当try里面的某条语句出现错误的时候,就不在继续执行try中的语句,将会执行except里面的异常处理语句。
try:
print(test)
except:
print('程序出现异常')
try:
print(smcs)
print(1/0)
except ZeroDivisionError:
print('程序出现异常——除数为0')
except NameError:
print('程序出现异常——为声明变量')
如果一个except语句向捕获多个异常,并使用同一种处理方式:
try:
print(smcs)
print(1/0)
except (NameError, ZeroDivisionError):
print('程序出现异常')
try:
print(smcs)
print(1/0)
except (NameError, ZeroDivisionError) as e:
print('程序出现异常%s',e)
try:
print(smcs)
print(1/0)
except :
print('程序出现异常')
还有一种就是在except后面使用Exception类。由于Exception类是所有异常类的父类,因此可以捕获所以异常。
try:
print(smcs)
print(1/0)
except Exception as e:
print('程序出现异常%s', e)
try:
print('三木成森')
except Exception as e:
print('程序出现异常%s', e)
else:
print('没有异常')
有一种情况,不管是否捕捉到异常,都要执行一些终止行为
try:
print('三木成森')
except Exception as e:
print('程序出现异常%s', e)
finally:
print('终止行为')
抛出异常使用raise和assert语句
使用raise语句能显示的触发异常,基本格式:
raise 异常类 # 引发异常时会隐式的创建对象
raise 异常类对象 # 引发异常类实例对象对应的异常
raise # 重新引发刚刚发生的异常
当raise语句指定异常的类名时,会创建该类的实例对象,然后引发异常
raise IndexError
运行结果:
Traceback (most recent call last):
File "F:\Demo\Python\Chapter9\异常.py", line 47, in
raise IndexError
IndexError
index = IndexError()
raise index
运行结果:
Traceback (most recent call last):
File "F:\Demo\Python\Chapter9\异常.py", line 50, in
raise index
IndexError
不带任何参数的raise,可以再次引发刚刚发生过的异常,作用就是向外传递异常。
try:
raise IndexError
except:
print('异常')
raise
运行结果:
异常
Traceback (most recent call last):
File "F:\Demo\Python\Chapter9\异常.py", line 53, in
raise IndexError
IndexError
当使用raise语句抛出异常时,还能给异常指定描述信息。
raise IndexError("索引下标超出范围")
运行结果:
Traceback (most recent call last):
File "F:\Demo\Python\Chapter9\异常.py", line 58, in
raise IndexError("索引下标超出范围")
IndexError: 索引下标超出范围
如果要在一个异常中抛出异常,可以使用raise-from
语句
try:
num
except Exception as e:
raise IndexError('下标超出范围') from e
运行结果:
Traceback (most recent call last):
File "F:\Demo\Python\Chapter9\异常.py", line 61, in
num
NameError: name 'num' is not defined
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "F:\Demo\Python\Chapter9\异常.py", line 63, in
raise IndexError('下标超出范围') from e
IndexError: 下标超出范围
try
里只定义了num
变量,没有为其赋值,所以会引发NameError
异常,使得程序跳转到except
子句中执行,except
可以捕捉到所有异常,并且使用raise-from
抛出异常后在抛出“下标超出范围”的异常。
assert
又称为断言,值得时期望用户满足指定额条件。当用户定义的约束条件不满足的时候,会触发AssertionError
异常,所有assert
语句可以当做条件式的raise语句。
assert语句格式:assert 逻辑表达式, data
assert后面紧跟着一个逻辑表达式,相当于条件。data通常时一个字符串,当表达式的结果为False时,作为异常类型的描述信息使用。
a = 0
assert a!=0, 'a不能等于0'
运行结果:
Traceback (most recent call last):
File "F:\Demo\Python\Chapter9\异常.py", line 66, in
assert a!=0, 'a不能等于0'
AssertionError: a不能等于0
assert语句用来收集用户自定义的约束条件,而不是捕捉内在的程序设计错误,因为Python会自行收集程序的设计错误,会在遇见错误是自动引发异常。
try:
a = input()
assert int(a)!=0, 'a不能等于0'
except Exception as e:
print('捕捉到异常:', e)
运行结果:
0
捕捉到异常: a不能等于0