文章目录
异常处理
1. 什么是异常
程序在运行时,如果 Python 解释器
遇到 到一个错误,会停止程序的执行,并且提示一些错误信息,这就是 异常
异常是因为程序出现了错误,而在正常控制流以外采取的行为
- 这个行为又分为两个阶段:
- 首先是引起异常发生的错误
- 然后是检测(和采取可能的措施)阶段
2. Python 中的异常
当程序运行时,因遇到未解的错误而导致中止运行,便会出现 traceback 消息,打印异常
KeyboardInterrupt # Ctrl + C,会产生用户中断执行错误
EOFError # Ctrl + D,会产出此错误
python 中异常演示
>>> a + 5 # NameError,变量a没有定义
>>> 'hello'[5] # IndexError,字符串hello的最长索引下标为4
>>> a = 10
>>> if a = 10: # SyntaxError,python中的等于号使用'=='表示
>>> n = input('number:' ) # 要求输入number时,Ctrl + D, 产生EOFError
>>> n = input('number: ') # Ctrl + C,产生KeyboardInterrupt,用户中断执行
错误类型捕获
- 在程序执行时,可能会遇到 不同类型的异常,并且需要 针对不同类型的异常,做出不同的响应,这个时候,就需要捕获错误类型了
- 语法如下:
try:
# 尝试执行的代码
pass
except 错误类型1:
# 针对错误类型1,对应的代码处理
pass
except (错误类型2, 错误类型3):
# 针对错误类型2 和 3,对应的代码处理
pass
except Exception as result:
print("未知错误 %s" % result)
try-except 语句
- 定义了进行异常监控的一段代码,并且提供了处理异常的机制
try:
n = int(input('number: ')) # 没有输入任何值,回车,产生ValueError异常
print(n)
except ValueError:
print('无效的输入') # 当异常ValueError发生时,执行print()
带有多个 expect 的 try 语句
- 可以把多个 except 语句连接在一起,处理一个try 块中可能发生的多种异常
# 使用多个expect的try语句,处理异常
try:
n = int(input('number: ')) # 没有输入任何值,回车,产生ValueError异常
print(n)
except ValueError: # 当异常ValueError发生时,执行print()
print('无效的输入')
except KeyboardInterrupt: # Ctrl + C,产生KeyboardInterrupt,用户中断执行
print('\nBye-bye')
except EOFError: # Ctrl + D, 产生EOFError, 没有内建输入
print('\nBye-bye')
- 检测上述模块中异常处理结果
[root@localhost xxx] # python day01.py
number: # 回车,ValueError异常,s输入错误类型
无效的输入
[root@localhost xxx] # python day01.py
number: ^CBye-bye # Ctrl + C,KeyboardInterrupt异常,用户操作中断
[root@localhost xxx]# python day01.py
number: Bye-bye # Ctrl + D, EOFError异常, 没有内建输入
捕获未知错误
- 在开发时,要预判到所有可能出现的错误,还是有一定难度的
- 如果希望程序 无论出现任何错误,都不会因为
Python
解释器 抛出异常而被终止,可以再增加一个except
语法如下:
except Exception as result:
print("未知错误 %s" % result)
异常参数
- 异常也可以有参数,异常引发后它会被传递给异常处理器
- 当异常被引发后参数是作为附加帮助信息传递给异常处理器的
查看异常提示信息
>>> n = int(input('number: '))
number: # 回车,ValueError异常
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: ''
使用多个expect的try语句,实现异常参数
try:
n = int(input('number: '))
print(n)
except ValueError as e: # 当异常ValueError发生时,将异常信息赋值给变量e
print('无效的输入', e) # print(), 打印异常信息
except KeyboardInterrupt:
print('\nBye-bye')
except EOFError:
print('\nBye-bye')
[root@localhost day01]# python day01.py
number: # 回车,ValueError异常
无效的输入 invalid literal for int() with base 10: '' # 输出异常信息
使用多个expect的try语句,捕获多个异常
try:
n = int(input('number: '))
print(n)
except ValueError as e:
print('无效的输入', e)
except (KeyboardInterrupt, EOFError): # 使用except捕获多个异常
print('\nBye-bye')
[root@localhost day01]# python day01.py
number: ^C # Ctrl + C,产生KeyboardInterrupt,用户中断执行
Bye-bye
[root@localhost day01]# python day01.py
number: # Ctrl + D, EOFError异常, 没有内建输入
Bye-bye
else 子句
- 在 try 范围中没有异常被检测到时,执行 else 子句
- 在else 范围中的任何代码运行前,try 中的所有代码必须完全成功
# else子句的使用
try: # 有可能发生异常的代码块
n = int(input('number: '))
except ValueError as e: # 当异常ValueError发生时,将异常信息赋值给变量e
print('无效的输入', e) # print(), 打印异常信息
except (KeyboardInterrupt, EOFError):
print('\nBye-bye')
else: # 当不发生异常时,要执行的代码块
print(n)
[root@localhost day01] # python day01.py
number: 19 # 正常输入,打印else
19
finally子句
- finally 子句是 无论异常是否发生,是否捕捉都会执行的一段代码
- 如果打开文件后,因为发生异常导致文件没有关闭,可能会发生数据损坏,使用finally 可以保证文件总是能正常的关闭
# finally子句的使用
try: # 有可能发生异常的代码块
n = int(input('number: '))
except ValueError as e: # 当异常ValueError发生时,将异常信息赋值给变量e
print('无效的输入', e) # print(), 打印异常信息
except (KeyboardInterrupt, EOFError):
print('\nBye-bye')
exit() # 退出程序
else: # 当不发生异常时,要执行的代码块
print(n)
finally: # 不管异常是否发生都会执行代码块
print('Done')
[root@localhost day01]# python day01.py
number: # Ctrl + D, EOFError异常, 没有内建输入
Bye-bye
Done # 出现异常,finally 继续执行
[root@localhost day01]# python day01.py
number: 19 # 正常输入整数,打印结果
19
Done # 没有出现异常,finally 还是继续执行
练习 3:简化除法判断
需求
- 提示用户输入一个数字作为除法
- 如果用户按下 Ctrl + C 或 Ctrl + D 则退出程序
- 如果用户输入非数字字符,提示用户应该输入数字
- 如果用户输入 0,提示用户 0 不能作为除法
# mydiv.py
try: # 有可能发生异常的代码块
n = int(input('number: '))
result = 100 / n
# 当异常ValueError发生时,将异常信息赋值给变量e
except (ValueError, ZeroDivisionError) as e:
print('无效的输入', e) # print(), 打印异常信息
except (KeyboardInterrupt, EOFError): # 出现异常,执行print(),exit()
print('\nBye-bye')
exit() # 退出程序
else: # 当不发生异常时,要执行的代码块
print(result)
finally: # 不管异常是否发生都会执行代码块
print('Done')
[root@localhost day01] # python3 mydiv.py
number: # 空值,回车,异常处理
无效的输入 invalid literal for int() with base 10: ''
Done # 不管异常是否发生,都会打印
# 使用python解释器,执行day01.py
[root@localhost day01]# python3 mydiv.py
number: 0 # 输入0,异常处理
无效的输入 division by zero
Done # 不管异常是否发生,都会打印
3. 自定义异常
抛出异常—raise
应用场景
- 在开发中,除了 代码执行出错
Python
解释器会 抛出 异常之外 - 还可以根据 应用程序 特有的业务需求 主动抛出异常
示例
- 提示用户 输入密码,如果 长度少于 8,抛出 异常
注意
- 当前函数 只负责 提示用户输入密码,如果 密码长度不正确,需要其他的函数进行额外处理
- 因此可以 抛出异常,由其他需要处理的函数 捕获异常
抛出异常
Python
中提供了一个Exception
异常类- 在开发时,如果满足 特定业务需求时,希望 抛出异常,可以:
- 创建 一个
Exception
的 对象 - 使用
raise
关键字 抛出 异常对象
- 创建 一个
需求
- 定义
input_password
函数,提示用户输入密码 - 如果用户输入长度 < 8,抛出异常
- 如果用户输入长度 >= 8,返回输入的密码
def input_password():
# 1. 提示用户输入密码
pwd = input("请输入密码:")
# 2. 判断密码长度,如果长度 >= 8,返回用户输入的密码
if len(pwd) >= 8:
return pwd
# 3. 密码长度不够,需要抛出异常
# 1> 创建异常对象 - 使用异常的错误信息字符串作为参数
ex = Exception("密码长度不够")
# 2> 抛出异常对象
raise ex
try:
user_pwd = input_password()
print(user_pwd)
except Exception as result:
print("发现错误:%s" % result)
练习 4:自定义异常
需求
- 编写第一个函数,接收姓名和年龄,如果年龄不在1到120之间,产生 ValueError 异常
# 编写函数get_info(),在文件user_info.py上操作
def get_info(name, age): # 定义函数,接收姓名和年龄
# 异常触发ValueError,提示信息为:无效的年龄(1 ~ 119)
if not 0 < age < 120:
raise ValueError('无效的年龄(1 ~ 119)')
# 当age在0 ~ 120的范围,else代码块执行
else:
print('%s is %s years old' %(name, age))
try: # 有可能发生异常的代码块
get_info('tom', 200)
except ValueError as e: # 当异常ValueError发生时,将异常信息赋值给变量e
print('Error:', e) # print(), 打印异常信息
exit() # 退出程序,不继续执行后续代码
print('Done') # exit(),退出后,此代码不执行