1 # 第23节课:异常
2 '''
3 本节概述:
4 1- 异常的概念
5 2- 异常的产生
6 3- 异常的捕获和处理
7 4- 函数调用战法
8 5- 自定义异常
9 '''
10 # 1- 异常的概念:就是报错.代码执行产生错误,无法继续
11 # a = 8956 / 0
12 # print (a) #打印报错:ZeroDivisionError: division by zero
13 # b = [1,2]
14 # c = b[2]
15 # print(c+39) #打印报错:IndexError: list index out of range
16 # 理解异常:
17 # *当解释器遇到错误的,无法执行的代码
18 # *中断当前代码的执行,抛出一个异常对象
19 # sdfsdf #直接执行报错:NameError: name 'sdfsdf' is not defined
20 # NameError是异常对象的一种
21 # *开发者还可以自己定义异常对象
22 # *形形色色的异常,标识了不同的错误
23 # 例子:
24 # *输入0会导致当前程序异常退出
25 # while True:
26 # num = input('input a number:')
27 # print('100 / %s = %s' % (num,100.0/int(num)))
28 # 希望的行为:1.程序不要退出 2.提示用户输入错误 3.继续让用户重新输入数字,继续执行
29 # if过滤:事前处理.可处理已知的bug,如除数输入0是已知的
30 # 异常处理属于事后处理 即问题已经出现了,要去解决不让代码因报错而停止.可以有适当提示.
31
32 # 3- 异常的捕获和处理
33 # while True:
34 # num = input('input a number:')
35 # try:
36 # print('100 / %s = %s' % (num,100.0/int(num)))
37 # except ZeroDivisionError: #捕获一种异常,这种异常是已知的
38 # print ('除数不能为0')
39 # except ValueError:
40 # print('只能输入数字哦!') #捕获多种异常
41
42 '''
43 捕获后得到详细的异常信息:
44 try:
45 ohmy
46 except NameError as e:
47 print('handle NameError:',e)
48 # e 就是异常对象
49 # 我们可以打印出储存里面储存的具体错误信息
50 '''
51 # 怎么打印报错具体信息实例:
52 # while True:
53 # num = input('input a number:')
54 # try:
55 # print('100 / %s = %s' % (num,100.0/int(num)))
56 # except ZeroDivisionError as e: #捕获一种异常,这种异常是已知的
57 # print ('除数不能为0')
58 # print( e) #打印得报错具体信息:handle NameError: float division by zero
59 # except ValueError as v:
60 # print('只能输入数字哦!') #打印得:invalid literal for int() with base 10: 'x'
61 # print(v)
62 # except Exception: #查看可知这个Exception是前面两个异常类的父类.也可直接写作:
63 # except: #表示不管有什么错误,都执行冒号以后的操作
64 # except Exception as ree:
65 # print('异常了,这个异常是前面两种异常都没有抓到的其它异常',ree)
66 ''''''
67 '''
68 ZeroDivisionError 指明专门捕获ZeroDivisionError异常
69 NameError 指明专门捕获NameError异常
70 对应的处理代码区块
71 执行结果
72 是NameError 而不是 ZeroDivisionError
73 '''
74 # 怎么知道异常信息?
75 # import traceback
76 # while True:
77 # num = input('input a number:')
78 # try:
79 # print('100 / %s = %s' % (num,100.0/int(num)))
80 # except :
81 # print ('除数不能为0\n'+ traceback.format_exc())
82 # #如果输入的值不是数字,就会打印:ValueError: invalid literal for int() with base 10: 'b'
83 # #如果输入的数字是0.则会打印:ZeroDivisionError: float division by zero
84 # else: #注:如果前面抓到异常,else语句不执行,如果没有抓到异常才会执行这一句
85 # print('no exception之后就得放这个else,必须放在所有except代码块后面,finally之前')
86 # finally:#不管有没有抓到异常都会执行finally语句
87 # print('try except代码块的结束,要放finally语句')
88
89 # 4- 函数调用栈:
90 '''
91 1.文件读操作.txt .log 文件不存在会直接报错
92 fo=open('gfre')
93 2.异常机制使用场景:
94 boss布置任务:十个自动化测试用例的测试
95 小明如果跑到第三个出问题卡了,就得修好第三个之后才能跑下面的,如果有异常机制,就可以略过第三个就跑下面的.
96 直接跑完十个用例,然后反馈那几个有问题再针对性地修
97 **函数的调用:从上往下调用--类似于公告的发布
98 **异常的抛出:从下往上 --类似于事故的上报
99 **看报错信息:
100 1.如果调用第三方库的方法,控制台第一个 2.根本错误原因在最后一个信息。 所以看到很多个报错不要慌,因为都是最后一个报错才是根本原因
101 '''
102 # 1.
103 # fo=open('gfre') #直接报错了:FileNotFoundError: [Errno 2] No such file or directory: 'gfre'
104 # try:
105 # fo = open('gfre')
106 # except:
107 # print('请检查文件路径')
108
109 # # 异常的报错顺序:
110 # def f3(): #相当于区
111 # print('in f3 - begin')
112 # b=4/0
113 # print('in f3 - end')
114 # def f2(): #相当于市
115 # print('in f2 - begin')
116 # f3()
117 # print('in f2 - end')
118 # def f1(): #相当于省
119 # print('in f1 - begin')
120 # try:
121 # f2()
122 # except:
123 # print('f2报错了')
124 # print('in f1 - end')
125 # f1() #相当于北京
126 # 这里如果要加异常机制,不应在f3源头里面加,比如代码:fo = open('gfre')是open报错的,不可能让开发团队去把open函数的代码改了。买彩票,不可能自己写个数字去让彩票官方团队去把中奖号码写成你的号码
127 '''
128 以下是报错信息:可能函数本身没错,所以,谁调用抛给谁,一层一层往上抛.f1报错,是f2导致的-->
129 抛给f2.f2报错是f3导致的-->抛给f3.f3报错是某一行代码导致的.揪出这行代码.这是一个连锁反应
130 Traceback (most recent call last):
131 File "C:/Users/86199/Desktop/python/第23节课异常.py", line 118, in <module>
132 f1()
133 File "C:/Users/86199/Desktop/python/第23节课异常.py", line 116, in f1
134 f2()
135 File "C:/Users/86199/Desktop/python/第23节课异常.py", line 112, in f2
136 f3()
137 File "C:/Users/86199/Desktop/python/第23节课异常.py", line 108, in f3
138 b=4/0
139 ZeroDivisionError: division by zero
140 in f1 - begin
141 in f2 - begin
142 in f3 - begin
143 Process finished with exit code 1
144 '''
145
146 # 5- 自定义异常
147 # **继承至Exception *注意,一定要继承Exception这个类才是异常类
148 # class NameTooLongError(Exception):
149 # pass
150 # class NameTooShortError(Exception):
151 # pass
152 # # **使用raise抛出:
153 # raise NameTooLongError
154 # **抛出异常使用场景:
155 # *********函数出现错误,代码无法正常运行的情况下
156 # *********告诉上册调用代码,什么样执行错误产生了
157 # *********由上层代用代码决定如何处理
158 # # 自定义异常实例:
159 # class NameTooLongError(Exception):
160 # err ='name.long'
161 # print('名字太长了')
162 # def methFun(self):
163 # pass
164 # class NameTooShort(Exception):
165 # err ='name.short'
166 # print('名字太短了!')
167 # def methFun(self):
168 # pass
169 # def inputName():
170 # name=input('请输入用户名:') #5-10
171 # if len(name) > 10:
172 # raise NameTooLongError #自定义的异常要自行抛出来
173 # elif len(name) < 5:
174 # raise NameTooShort
175 # try:
176 # inputName()
177 # except NameTooLongError:
178 # print('您输入的名字太长了!')
179 # except NameTooShort as ns:
180 # print('您输入的名字太短了!',ns.err)
181 # ns.methFun()
182
183 # # 还可以自定义抛异常:
184 # for one in range(0,5):
185 # if one == 3:
186 # exit() #这里退出的话,就不打印后面那句话了
187 # raise ValueError('这是我的自定义异常')
188 # print(one)
189 # ###exit()不跑异常,直接退出
190
191 # # 断言:assert---检查点-----如果后续代码比较重要,而且很依靠前面的数据或者状态
192 # tel = input('请输入手机号:')
193 # assert len(tel) ==11,'手机位数有误!'
194 # print('我在处理手机运营商操作') #这就是断言,如果手机位数是11位,就是正常的,如果位数不对,就报错:AssertionError: 手机位数有误!
195 # # 断言和if是有区别的:if只是报错,没有挂掉,而断言是报错之后挂掉