Python基础25 异常堆栈跟踪,释放资源,自定义异常和主动抛出

主动抛出和自定义异常还有点问题,之后抽空完成

  1 #异常处理
  2 
  3 #try-except嵌套
  4 #try和except也是可以嵌套的
  5 #和if-else不同的是
  6 #try-except的嵌套是判定异常的,如果内部出现异常
  7 #就会优先判定内部的except,如果没有找到合适的
  8 #就会跳出,到外面的except中来寻找
  9 
 10 import datetime as dt
 11 
 12 def read_date_form_file(filename):
 13     try:
 14         file=open(filename)
 15         try:
 16             in_date=file.read()
 17             in_date=in_date.strip()
 18             date=dt.datetime.strptime(in_date,"%Y-%m-%d")
 19             return date
 20         except ValueError as e:
 21             print("内层处理ValueError异常")
 22             print(e)
 23     except FileNotFoundError as e:
 24         #没有找到文件
 25         print("外层处理FileNotFoundError异常")
 26         print(e)
 27     except OSError as e:
 28         #输入输出异常
 29         print("外层处理OSError异常")
 30         print(e)
 31 
 32 #这里我们就完成了对try-except的嵌套
 33 #直观的来看,程序显然变得复杂了
 34 #所以一般情况下,我们尽可能的不去使用这种嵌套的形式
 35 
 36 date_1=read_date_form_file('C:/Users/admin/source/repos/Rush_B/Rush_B/yichang/date_source.txt')
 37 print(date_1)
 38 #这样便可以正常输出了
 39 #我们再来查看一下except的异常抛出
 40 date_1=read_date_form_file('C:/Users/admin/source/repos/Rush_B/Rush_B/yichang/date_source_2.txt')
 41 print(date_1)       #date_source_2.txt文件内容为20BB-10-25
 42 #内层处理ValueError异常,抛出成功
 43 date_1=read_date_form_file('C:/Users/admin/source/repos/Rush_B/Rush_B/yichang/fake.txt')
 44 print(date_1)
 45 #外层处理FileNotFoundError异常
 46 #[Errno 2] No such file or directory: 'C:/Users/admin/source/repos/Rush_B/Rush_B/yichang/fake.txt'
 47 #这里显然关于文件存不存在的问题,内部的except是没有解决办法的
 48 #所以这里自然的寻找到了外层的except中来
 49 
 50 print("///////////////////////")
 51 
 52 #多重异常捕获
 53 #简单点来将,就是在except()括号中写多个异常的名字
 54 #就会自动去判定异常了
 55 #这里不做赘述
 56 '''
 57     except (FileNotFoundError,ValueError) as e:
 58 
 59         print(e)
 60         #类似于此的方法
 61 '''
 62 
 63 print("///////////////////////////")
 64 
 65 #异常堆栈跟踪
 66 #我们可以通过Python中的内置模块traceback的print_exc()函数来实现
 67 #它可以打印堆栈跟踪信息
 68 #基本格式如下:
 69 #traceback.print_exc(limit=None,file=None,chain=True)
 70 #                  limit表示限制堆栈跟踪的个数,None表示不限制个数
 71 #                           file表示是否输出堆栈跟踪的信息到文件里去,默认None表示不输入信息进文件
 72 #                                   chain为True表示将__cause__和__context__等属性连接起来,就像解释器本身打印一样
 73 
 74 import datetime as dt
 75 import traceback as tb
 76 
 77 def read_date_from_file_2(filename):
 78     try:
 79         file=open(filename)
 80         in_date=file.read()
 81         in_date=in_date.strip()
 82         date=dt.datetime.strptime(in_date,"%Y-%m-%d")
 83         return date
 84     except (ValueError,OSError) as e:
 85         print("请调用method_1方法解决")
 86         tb.print_exc()
 87 
 88 date_2=read_date_from_file_2('C:/Users/admin/source/repos/Rush_B/Rush_B/yichang/fakething.txt')
 89 print("日期={0}".format(date_2))
 90 #我们这里调用的是fakething就是不存在的文件
 91 #然后返还了堆栈数据:
 92 #Traceback (most recent call last):
 93  # File "C:\Users\admin\source\repos\Rush_B\Rush_B\yichang\yichang_2.py", line 79, in read_date_from_file_2
 94   #  file=open(filename)
 95 #FileNotFoundError: [Errno 2] No such file or directory: 'C:/Users/admin/source/repos/Rush_B/Rush_B/yichang/fakething.txt'
 96 #就可以更加准确的看到错误的地方
 97 
 98 print("///////////////////////////")
 99 
100 #finally和else在之前的一章有讲过
101 #但是不够仔细
102 #这里再仔细讲一遍
103 
104 #释放资源
105 #有时候try-except会占用很多资源
106 #所以这里我们用finally或者as with来释放资源
107 
108 #try-except-finally代码块
109 #try和except运行完后用finally来释放资源
110 
111 def read_date_form_file_3(filename):
112     try:
113         file=open(filename)
114         in_date=file.read()
115         in_date=in_date.strip()
116         date=dt.datetime.strptime(in_date,"%Y-%m-%d")
117         return date
118     except(ValueError,OSError):
119         print("出现异常")
120     finally:
121         file.close()
122 
123 date_3=read_date_form_file_3('C:/Users/admin/source/repos/Rush_B/Rush_B/yichang/date_source.txt')
124 print("日期={0}".format(date_3))
125 #这里我就成功运行了
126 #这里通过finally的file.close()完成了对文件的关闭
127 #从而达到了释放资源的目的
128 #我们再进行一次尝试
129 #date_3=read_date_form_file_3('C:/Users/admin/source/repos/Rush_B/Rush_B/yichang/fake.txt')
130 #print("日期={0}".format(date_3))
131 #但是这次却报错了,为什么?
132 #原因其实很简单,我们导入的filename是假的,系统是找不到这个文件的
133 #所以这里我们会抛出异常,但是最后运行的finally代码块是 file.close()
134 #由于文件根本不存在,没有打开过文件,所以这里的file.close()自然无法关闭
135 #就会报错
136 
137 #接下来我们可以通过else来完善这个代码块
138 
139 
140 def read_date_form_file_4(filename):
141     try:
142         file=open(filename)
143     except OSError:         
144         print("文件未打开")
145     else:                           #通过else成功分成了两种情况
146         print("文件成功打开了")
147         try:
148             in_date=file.read()
149             in_date=in_date.strip()
150             date=dt.datetime.strptime(in_date,"%Y-%m-%d")
151             return date
152         except(ValueError,OSError):
153             print("出现异常")
154         finally:                    #也就将finally代码块放置在了文件以及打开了区域
155             file.close()
156 
157 date_4=read_date_form_file_4('C:/Users/admin/source/repos/Rush_B/Rush_B/yichang/date_source.txt')
158 print("日期={0}".format(date_4))
159 
160 #即使存在文件未打开,也不会影响运行
161 date_4=read_date_form_file_4('C:/Users/admin/source/repos/Rush_B/Rush_B/yichang/fake.txt')
162 print("日期={0}".format(date_4))
163 
164 print("///////////////////")
165 
166 #with as 代码块自动管理资源
167 #with as 模块可以自动的释放资源,在as后面声明一个资源变量
168 #在with as代码块执行完毕后会自动的释放资源
169 
170 def read_date_from_file_5(filename):
171     try:
172         with open(filename) as file:    #这里是定义了一个资源文件file然后执行了open
173             #这里就是with as定义的代码块
174             in_date=file.read()
175             #在执行完读取file里的数据以后
176             #立刻执行上面as
177             #立刻释放file的资源
178         in_date=in_date.strip()
179         date=dt.datetime.strptime(in_date,"%Y-%m-%d")
180         return date
181     except(ValueError,OSError):
182         print("出现异常")
183     
184 date_5=read_date_from_file_5('C:/Users/admin/source/repos/Rush_B/Rush_B/yichang/date_source.txt')
185 print("日期={0}".format(date_5))
186 
187 print ("////////////////////////////")
188 
189 #自定义异常类
190 #一般来讲会开发自己的Python的库的时候
191 #基本上都会自己来定义一些异常类
192 #实现定义异常类需要继承Exception类或其子类
193 
194 class MyException(Exception):   #定义一个异常类,并将Exception作为父类
195     def __init__(self,message):     #这里message是异常描述信息
196         super().__init__(message)   #这里是调用父类Exception的代码
197         #这样这个我们定义的自定义类就包括了系统的所有异常
198 #接下来
199 #我们再根据需要来定义新的异常类型,但是这时候父类就要写我们的自定义异常类
200 
201 class GeshiError(MyException):
202     
203     def __init__(self,a,b):         #定义两个数据待会方便收录
204         self.a=a
205         self.b=b
206         #但是这个例子中暂时不需要这个
207     
208 
209     def __str__(self):              #然后这里重新定义一下str然后再输出数据
210         return "日期的格式出错了"
211 #这样建立的目的是为了后面方便通过raise来显示化抛出异常
212 
213 
214 
215 
216 print("////////////////////////")
217 
218 #显示抛出异常
219 #我们之前接触的异常都是由系统生成的
220 #当异常抛出的时候,系统会创建一个异常对象然后抛出
221 #单也可以通过raise语句显示抛出异常
222 #格式:
223 #raise BaseException 或其子类实例
224 #简单来讲就是 raise 后面添加基础异常的名字,或者我们自己定义的异常
225 
226 def read_date_from_file_6(filename):
227     try:
228         c=1
229         file=open(filename)            
230         in_date=file.read()
231         in_date=in_date.strip()
232         date=dt.datetime.strptime(in_date,"%Y-%m-%d")
233         if c==1 :
234             raise MyException("C==1")
235         return date
236     except ValueError as e:
237         raise MyException('1') 
238     except OSError as e:
239         raise MyException("2") 
240     except FileNotFoundError as e:
241         raise MyException("3") 
242     except MyException as e:
243         print(e)
244 
245     
246 date_6=read_date_from_file_6('C:/Users/admin/source/repos/Rush_B/Rush_B/yichang/date_source.txt')
247 print("日期={0}".format(date_6))
248 #输出一个错误的格式
249 date_7=read_date_from_file_6('C:/Users/admin/source/repos/Rush_B/Rush_B/yichang/date_source_2.txt')
250 print("日期={0}".format(date_7))
251 
252 #和try-except不同的是 raise手动抛出异常以后,就不会继续运行了
253 print("还在正常运行呢。")

 

posted @ 2020-10-29 15:10  想活出点人样  阅读(273)  评论(0编辑  收藏  举报