了解异常
当检测到一个错误时,解释器就无法继续执行后面的代码了,而且出现了一些错误提示,这就是所谓的"异常"。
例如:以r
方式打开一个不存在的文件。
open('test.txt', 'r')
有时候我们想要控制发生异常后继续发生的事情,比如给出明显的提示,又如作出相应的异常处理,这时候就要学习Python当中有关异常处理的语法。
异常处理的写法
基本处理
- 出现异常后,我们希望代码能够作出相应处理,继续正常运行之后的代码。
语法
try:
代码块1(可能出现异常)
except:
代码块2(代码块1出现异常后执行的代码)
...
#之后的代码
如:
尝试以r
模式打开文件,如果文件不存在,则以w
方式打开。
try:
f = open('test.txt', 'r')
except:
print("文件不存在,正在创建...")
f = open('test.txt', 'w')
#文件不存在,正在创建...
捕获指定异常
- 异常的产生可能是方方面面的,我们需要知道如何捕获指定类型的异常。
- 常见的异常类型:
异常类型(类) | 详细原因 |
---|---|
AttributeError | 想访问的属性不存在 |
IndexError | 索引越界 |
KeyError | 想访问的键key在字典中不存在 |
NameError | 想访问的变量不存在 |
TypeError | 数据类型(类)之间无效的运算操作 |
ZeroDivisionError | 做除法时分母为0 |
ValueError | 传入的值非法 |
FileNotFoundError | 要读取的文件不存在 |
语法
try:
代码块1(可能出现各种异常)
except 某种异常类型(类):
代码块2(如果捕获到该异常类型后执行的代码)
except 某种异常类型(类):
代码块3(如果捕获到该异常类型后执行的代码)
如:
while(True):
try:
x=int(input("请输入一个数字:"))
except ValueError:
print("请输入数字!")
try:
print(f"{x}的倒数为{1/x}")
except ZeroDivisionError:
print("分母为0,请重新输入!")
注意:
- 如果
except
后面出现的异常类型和实际出现的异常类型不一致,则无法捕获该异常。- 一般try下方只放一行尝试执行的代码。
同时捕获处理多个异常
想同时捕获并一并处理多个异常时,可以把要捕获的异常类型的名字,放到except 后,并使用元组的方式进行书写。
语法
try:
代码块1(可能出现各种异常)
except (异常类型1,异常类型2...):
代码块2(一旦捕获到元组中某种异常后执行的代码)
如:
while(True):
x=input("请输入一个非0数字:")
try:
x=int(x)
print(f"{x}的倒数为{1/x}")
except (ValueError,ZeroDivisionError):
print("输入有误,请重新输入!")
捕获异常并打印描述信息
- 上述异常类型都是Python内置的异常类,用
print()
能打印相关异常信息,而不停止代码的运行
如:
while(True):
x=input("请输入一个非0数字:")
try:
x=int(x)
print(f"{x}的倒数为{1/x}")
except (ValueError,ZeroDivisionError) as error:
print(error)
捕获所有异常
Exception
是所有常见程序异常类的父类。except Exception
能够捕获所有类型的异常
while(True):
x=input("请输入一个非0数字:")
try:
x=int(x)
print(f"{x}的倒数为{1/x}")
except Exception as error:
print(error)
异常的else
- else表示的是如果没有异常要执行的代码。
语法
try:
代码块1(可能出现异常)
except:
代码块2(代码块1出现异常后执行的代码)
else:
代码块3(代码块1没有发生异常时执行的代码)
...
#之后的代码
如:
#'test.txt'已存在
try:
f = open('test.txt', 'r')
except FileNotFoundError:
print("文件不存在,正在创建...")
f = open('test.txt', 'w')
else:
print("文件已找到,正在打开...")
#文件已找到,正在打开...
异常的finally
- finally表示的是无论是否异常都要执行的代码。
语法
try:
代码块1(可能出现异常)
except:
代码块2(代码块1出现异常后执行的代码)
else:
代码块3(代码块1没有发生异常时执行的代码)
finally:
代码块4(无论代码块1是否发生异常都要执行)
...
#之后的代码
如:
try:
f = open('test.txt', 'r')
except FileNotFoundError:
print("文件不存在,正在创建...")
f = open('test.txt', 'w')
else:
print("文件已找到,正在打开...")
finally:
print("已成功打开文件,这就去关闭...")
f.close()
#if存在:
#文件已找到,正在打开...
#已成功打开文件,这就去关闭...
#if不存在:
#文件不存在,正在创建...
#已成功打开文件,这就去关闭...
异常的传递
- 异常语句内可嵌套异常语句
- 如果内层
try
引发异常,异常最先交给内层的except
,如果内层except
没有处理该类型异常的代码,则传递给外层except
;如果所有层的except
都不能处理,就会以默认形式处理,即中断代码运行。
import time
try:
f = open('test.txt')
try:
while True:
content = f.readline()
if len(content) == 0:
break
time.sleep(2)
print(content)
except:
# 如果在读取文件的过程中,产生了异常,那么就会捕获到
# 比如 按下了 ctrl+c
print('意外终止了读取数据')
finally:
f.close()
print('关闭文件')
except:
print("没有这个文件")
自定义异常
- 我们可以自己设计一个异常类,并在指定判断条件下通过
raise
语句在try
中抛出该异常,再在except
内进行处理
语法
#自定义异常类
class ErrorName(Exception):
def __init__(self):
代码块
# 设置自定义异常的描述信息
def __str__(self):
return "异常描述"
try:
if("指定判断条件"):
raise ErrorName()
except ErrorName as error:
print(error)
如:
密码长度不足,则报异常(用户输入密码,如果输入的长度不足3位,则抛出自定义异常,并捕获该异常)。
# 自定义异常类,继承Exception
class ShortInputError(Exception):
def __init__(self, length, min_len):
self.length = length
self.min_len = min_len
# 设置抛出异常的描述信息
def __str__(self):
return f'输入字符不能少于{self.min_len},你输入的长度是{self.length}'
try:
code = input('请输入密码:')
if len(code) < 3:
raise ShortInputError(len(code), 3)
except ShortInputError as error:
print(error)
else:
print('密码输入完成')