一、异常
程序执行过程中出现的非正常流程现象
二、异常处理的格式
1.异常处理格式一
""" 最简单语法格式1 try: ____可能引发异常现象的代码 except: ____出现异常现象的处理代码 """ print("程序开始") try: # i = 5 print(i) # 此时i没有定义 except: print("前面的代码有异常")
print("程序结束")
运行结果:
程序开始
前面的代码有异常
程序结束
# try下面的代码有部分异常
print("程序开始了") try: # 这里的代码有可能引发异常 i = 5 print(i) # a = 10 print(a) except: print("24-27行代码之间出现了异常") print("程序结束了")
运行结果:
程序开始了
5
24-27行代码之间出现了异常
程序结束了
# 代码由上至下执行,打印”程序开始了“之后,开始进入try代码中,检查try下面的代码i= 5,并打印了5,再往下,a没有定义,到了”print(a)“,代码异常,就跳过进入了except中,打印了”
24-27行代码之间出现了异常
“
再往下打印了”程序结束了“
# try下面的代码中,中间部分的代码异常
print("程序开始了") try: # 这里的代码有可能引发异常 i = 5 print(i) # a = 10 print(a) b = 6 print(6) except: print("24-27行代码之间出现了异常") print("程序结束了")
运行结果:
程序开始了
5
24-27行代码之间出现了异常
程序结束了
# 代码由上至下执行,打印”程序开始了“之后,开始进入try代码中,检查try下面的代码i= 5,并打印了5,再往下,a没有定义,到了”print(a)“,代码异常,就跳过进入了except中,打印了”
24-27行代码之间出现了异常
“
# print(a)下面的代码没有问题,所以但是程序并没有执行,当再try里面的代码中,当一遇到问题,在try中,代码就会终止执行,直接进入except中
总结:
python是解释性语言,代码执行至上而下
1.当没有遇到异常,就会执行try里面的代码
2.当遇到异常就会执行except中的代码
3.代码从上至下执行,try前面的代码没有问题,后面的代码有异常,它会执行完前面的代码,然后遇到异常后,转到except中执行
4.代码执行,当try上中下三行代码,上和下的代码没有问题,中间的代码有问题,那么执行完上面的代码后,就会转到except代码中
2. 异常处理格式2
""" 语法格式二 最简单语法格式1 try: ____可能引发异常现象的代码 except: ____出现异常现象的处理代码 finally: ____try代码快结束后运行的代码 """
print("程序开始了") # 成功执行 f = open("1.txt", "r", encoding="utf8") # 这里启动的模式是r,需要关闭文件之后,在拿到文件句柄进行写操作 f.write("hello world!!!") # 引发异常 f.close() # 执行不到 print("程序结束了") # 执行不到
# 当read模式成功执行后,因为后面的write方法与模式对应不上,报错导致后面的代码都无法执行了,进而引发这个文件的资源没有释放
运行结果:
FileNotFoundError: [Errno 2] No such file or directory: '1.txt'
程序开始
# 解决方式1:
print("程序开始了")
try:
f = open("1.txt", "r", encoding="utf8")
f.write("hello world!!!") # 引发异常
f.close()
except:
f.close()
print("出现异常")
print("程序结束了")
运行结果:
程序开始了
出现异常
程序结束了
# 当出现了这种情况的时候
# 从代码上看try中的代码没有问题,但是没有关闭文件操作,这样文件的资源就有可能不会得到释放,但是又不会进入except,所以为了确保文件得到释放,还需要上一道保险
print("程序开始了")
try:
f = open("1.txt", "r", encoding="utf8")
f.read() # 引发异常
except:
f.close()
print("出现异常")
print("程序结束了")
运行结果:
程序开始了
程序结束了
print("程序开始了")
try:
f = open("1.txt", "r", encoding="utf8")
f.read()
# f.close()
except:
f.close()
print("出现异常")
time.sleep(30)
finally:
f.close()
print("已执行文件关闭")
print("程序结束了")
运行结果:
程序开始了
已执行文件关闭
程序结束了
# 不管try中的代码是不是有问题,except有没有执行,代码都会执行finally下面的代码
3.异常处理方式3
""" 语法格式三 最完整语法格式 try:(必选) ____可能引发异常现象的代码 except:(必选:二选一) ____出现异常现象的处理代码 else:(可选) ____未出现异常现象的处理代码 finally:(必选:二选一) ____try代码快结束后运行的代码 """
print("程序开始") try: i = 5 print(i) except: print("try中的代码有异常") else: print("try中代码没有异常") finally: print("比执行的代码") print("程序结束")
三.捕获具体异常
""" 捕获具体异常 except 异常名: """
# i = 1/0 # print(i) # ZeroDivisionError: division by zero
# 我们知道前面这几行代码是ZeroDivisionError异常
print("程序开始了")
try:
i = 1/0
print(i)
except NameError:
print("出现命名异常")
except ZeroDivisionError:
print("0不能作分母")
print("程序结束了")
运行结果:
程序开始了
0不能作分母
程序结束了
# 当遇到异常的时候,程序会走到相对应的异常类型里面
print("程序开始了") try: # i = "hello world" print(a) print(a.index("a")) # 这里的异常是value异常 except NameError: print("变量i没有被定义") except ValueError: print("字符串中没有该字符,憨批") except IndentationError: print("缩进错误") print("程序结束了") 运行结果: 程序开始了 变量i没有被定义 程序结束了
在上面的异常,都是我们可以预知到的异常,还有一些我们无法预知的异常,如果程序检索不到下面的具体异常,依然会报错
print("程序开始了") try: i = "hello world" print(i) print(i.index("a")) # 这里的异常是value异常 except NameError: print("变量i没有被定义") except IndentationError: print("缩进错误") print("程序结束了") 运行结果: 程序开始了 hello world Traceback (most recent call last): File "D:/zgzeng/pychon基础/异常处理/4-捕获异常.py", line 80, in <module> print(i.index("a")) # 这里的异常是value异常 ValueError: substring not found
这样我们就需要用到一个大范围的异常来我们自己未知异常,防止报错
print("程序开始了") try: a = "hello world" print(a) print(a.index("o")) # 这里的异常是value异常 j = 1/0 except NameError: print("变量i没有被定义") except ValueError: print("字符串中没有该字符,憨批") except IndentationError: print("缩进错误") except Exception: # 无差别捕获 未知的错误 放在最后面 print("未知的错误") print("程序结束了") 运行结果: 程序开始了 hello world 4 未知的错误 程序结束了
四、捕获异常具体信息
NameError:name 'a' is not defined
# NameError是异常类名
# name 'a' is not defined异常具体信息
"""
except 异常类名 as e:
"""
try:
# i = 5
print(i)
except NameError as e: # e只是一个变量名,我们可以设置为别的变量名,用来赋值给具体异常信息
print("具体的异常信息是:{}".format(e))
运行结果:
具体的异常信息是:name 'i' is not defined
# 这里将NameError的异常具体信息复制给了e
五、自定义异常
异常是一个类,Exception
为什么需要一个自定义异常,是因为我们有时候要写一个异常信息提示的时候,如果直接将原生的异常类写入,这样可能会影响这个类之后的使用,所以自定义一个异常,另外还有一些异常并不是原生异常类都能处理到,所以我们需要自定义异常
"""
自定义异常类
子类>>> 父类exception
定义类
"""
# 写一个程序,将下列不可以参军的人标记出来
info = {"小刚": 14} for name in info: if info[name] >= 18: print(f"{name}可以去当兵") else: print(f"{name}不能去当兵")
也可以用异常来标记
class AgeError(Exception):
pass
def check(info):
for s in info.keys():
global s1
s1 = s
if info[s] < 18:
raise AgeError("年龄不符合")
print(f"{s1}可以去当兵")
try:
check({"小平": 15})
except AgeError as e:
print(f"{s1}不能去当兵")
# raise AgeError("年龄不符合") raise声明这个异常,而括号里面的东西是异常具体信息
六.案例
""" 要求: 用户名输入用户名,密码后对信息进行校验 1.用户名长度再3-8个字符 2.用户名中只能出现英文字母和数字 3.密码长度必须是6位 4.密码必须由纯数字组成 """ # 1.通过用户输入去得到用户名和密码 usr_name = input("请输入您的用户名:") usr_password = input("请输入您的密码:") # 自定义异常,用来抛出,使得程序报错 class NameIsError(Exception): pass class NameClassError(Exception): pass class PasswordLengthIsError(Exception): pass class PasswordIsError(Exception): pass def check(name, pwd): """ 判断用户名和密码是否符合要求规范 :param name: 用户名 :param pwd: 密码 :return: none """ if len(name) not in range(3, 9): raise NameIsError("用户名的长度不在要求3-8个字符之间") if not name.isalnum(): raise NameClassError("用户名中只能出现英文字母和数字") if not len(pwd) == 6: raise PasswordLengthIsError("密码的长度必须是6个字符") if not pwd.isnumeric(): raise PasswordIsError("密码必须由纯数字组成") try: check(usr_name, usr_password) except NameIsError as e: print("用户名长度必须是3-8个字符之间") except NameClassError as e: print("用户名由英文字母和数字组成") except PasswordIsError as e: print("密码由纯数字组成") except PasswordLengthIsError as e: print("密码由6个字符组成")