1. 认识一下异常
在编写程序时,事件的异常是与正常过程相对立的,异常事件可能是错误(分母为0),或者是不希望经常发生的事情。Python用异常对象(exception object)来表示异常情况。程序遇到错误后,会引发异常,如果异常对象未被处理或捕获,程序就会终止执行。
2. 主动引发异常
关键字:raise
raise Exception
raise Exception('this is an exception.')
Exception类是Python内建的异常类
二者的区别:
写法一引发了一个没有任何有关错误信息的普通异常
写法二则添加了错误信息 this is an exception.
3. 常见内建异常类
- Exception:所有异常的基类
- AttributeException:特性引用或赋值失败时引发
- IOError:试图打开不存在文件(包括其他情况)时引发
- IndexError:在使用序列中不存在的索引时引发
- KeyError:在使用映射中不存在的键时引发
- NameError:在找不到名字(变量)时引发
- SyntaxError:在代码为错误形式时引发
- TypeError:在内建操作或者函数应用于错误类型的对象时引发
- ValueError:在内建操作或者函数应用于正确类型的对象,但是该对象使用不合适的值时引发
- ZeroDivisionError:在除法或者模除操作的第二个参数为0时引发
4. 自定义异常类
自定义类,继承Exception或者自定义的异常子类即可
class CustomException(Exception): pass
class SubCustomException(CustomException): pass
可以在自定义的异常类中加入一些特性、方法等
引发自定义异常,同用 raise CustomException 这样的方式(见上 2. 主动引发异常)
5. 捕获异常
关键字:try、except、finally
作用:
① 做出一些错误处理,输出一些更友好的错误信息
② 防止程序运行崩溃
③ 省去过多的if语句检验
5.1 捕获
try:
x=input('Number1: ')
y=input('Number2: ')
print(int(x)/int(y))
except ZeroDivisionError:
print('The second number can not be zero.')
此处捕获了ZeroDivitionError,当第二个输入为0时,控制台将会打印下面的语句
5.2 捕获并打印异常信息
try:
x=input('Number1: ')
y=input('Number2: ')
print(int(x)/int(y))
except ZeroDivisionError as e:
print('The second number can not be zero.')
print('ZeroDivisionError : ' + e)
当捕获多个异常时,可以通过多个except子句捕获,也可以通过一个except捕获多个
try:
x=input('Number1: ')
y=input('Number2: ')
print(int(x)/int(y))
except ZeroDivisionError as e:
print('The second number can not be zero.')
print('ZeroDivisionError : ' + e)
except TypeError as e:
print('TypeError : ' + e)
try:
x=input('Number1: ')
y=input('Number2: ')
print(int(x)/int(y))
except (ZeroDivisionError, TypeError) as e:
print('Exception : ' + e)
5.3 捕获后重新引发
try:
x=input('Number1: ')
y=input('Number2: ')
print(int(x)/int(y))
except ZeroDivisionError:
print('The second number can not be zero.')
raise
注意 raise 关键字,后面并没有带任何信息,表示直接引发当前捕获的异常
5.4 捕获所有异常
try:
x=input('Number1: ')
y=input('Number2: ')
print(int(x)/int(y))
except:
print('sth wrong happend.')
省略except子句所有的异常类
5.5 捕获异常,异常未发生时,还想执行点什么
满足上述场景时,我们可以直接在try/except代码块后面加上else子句
try:
x=input('Number1: ')
y=input('Number2: ')
print(int(x)/int(y))
except ZeroDivisionError:
print('The second number can not be zero.')
else:
print('right end.')
5.6 捕获异常,不论异常是否发生,最后都要执行点什么
满足上述场景时,我们可以直接在try/except代码块后面加上finally子句
try:
x=input('Number1: ')
y=input('Number2: ')
print(int(x)/int(y))
except ZeroDivisionError:
print('The second number can not be zero.')
else:
print('right end.')
finally:
print('do sth finally.')
异常捕获的代码块组合可以比较灵活,不同的组合注重异常的侧重点不同,所以需要编写程序时自行根据情况而定
try/except、try/finally、try/except/else、try/except/finally、try/except/else/finally(最完全格式)
6. 异常和函数
异常和函数能很自然地一起工作。如果异常在函数内引发而不被处理,它就会传播(浮到)函数调用的地方。如果在那里也没有处理异常,它就会继续传播,一直到达主程序(全局作用域)。如果那里没有异常处理程序,程序会带着栈跟踪中止。
def faulty():
raise Exception('sth is wrong.')
def ignore_exception():
faulty()
print('Exception ignored.')
def handle_exception():
try:
faulty()
except:
print('Exception handled.')
ignore_exception()
# 执行会报错,并打印错误栈跟踪信息,且Exception ignored. 不会打印到控制台
handle_exception()
# 执行不会报错,且Exception handled. 会打印到控制台
7. 异常与条件语句
通常一些已知即将发生的异常,可以通过条件语句实现和异常处理同样的功能,但是条件语句可能在自然性和可读性上差些,至于更喜欢哪种方法,完全是个人喜好。
# 检测对象是否存在特定属性,并打印
# if 写法
def describePerson(person):
print('name: ', person(['name']))
print('age: ', person(['age']))
if 'weight' in person:
print('weight: ', person(['weight']))
# try/except 写法
def describePerson(person):
print('name: ', person(['name']))
print('age: ', person(['age']))
try:
# 此处用+不用,的原因,用逗号会打印前面的weight: ,用加号是想避免这种情况,使结果共同打印出来
print('weight: ' + person(['weight']))
except: pass
Congratulations
Python进阶之异常的介绍到这里就结束了,更多进阶内容请继续关注,感兴趣记得订阅哦,感谢!!!