python中异常处理的一种特殊情况(try..finally...)(学习笔记)

事情的起因其实是我在学习上下文管理器(context manager)时偶然获得的奇怪的知识点,在python中异常处理是属于比较基础但是非常重要的知识点,之前学习了普通用法try…except…else…finally之后也就没有深究,最多也就是额外学习了一个自定义异常的用法。
贴上普通异常语法:

try:
    执行代码
except <可能的ERROR 1> as e:
    print(e)
except <可能的ERROR 2> as e:
    print(e)
except <可能的ERROR 3> as e:
    print(e)
except Exception as e:
	# 接住所有错误
	print(e)
else:
    print('try内没有异常')
finally:
    print('无论异常与否,都会执行')

那天碰到了try…finally…的用法,突然两眼一抹黑,因为当时的想法是:

如果连except都没有,不能接住报错,那么try的意义在哪里?

之后自己也一直在尝试各种姿势,也是一直没弄懂,后来在python专家群,请教了几位大佬之后,似乎好像现在已经弄懂了,大家可以在CSDN上搜索python专家门诊加入我们,这里感谢@poqweur和@NBody攻城狮两位群里的大佬答疑解惑,也希望大家能一起加入进来。

关于上下文管理器

这里直接贴代码,因为本笔记主要讲的是try…finally…

class Resource():
    def __enter__(self):
        print('===connect to resource===')
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
    	# 注意1:在__exit__方法中会自动处理异常
    	# 注意2:__exit__方法必不可少三个参数,用来处理异常
        print('===close resource connection===')
        
    def operate(self):
        print('===in operation===')

上下文管理器的作用:

  1. 可以以一种更加优雅的方式,操作(创建/获取/释放)资源,如文件操作、数据库连接;
  2. 可以以一种更加优雅的方式,处理异常

使用类是上下文管理器的一种方法,还有一种是使用contextlib装饰器

import contextlib
@contextlib.contextmanager
def open_func(file_name):
	print('open file:', file_name, 'in __enter__')
	file_handler = open(file_name, 'r')

	yield file_handler

	print('close file:', file_name, 'in __exit__')
	file_handler.close()
	return

with open_func('1.txt') as file_in:
	print(file_in.read())

使用装饰器的方法无法接住异常,需要手动使用try语法,当时也是看了这段代码懵逼了。

以下为正文

import contextlib

@contextlib.contextmanager
def open_func(file_name):
	print('open file:', file_name, 'in __enter__')
	file_handler = open(file_name, 'r')

	try:
		yield file_handler
	finally:
		# 注意这里的异常语法中没有except
		# 注意return的位置
		print('close file:', file_name, 'in __exit__')
		file_handler.close()
		return
with open_func('1.txt') as file1:
	print(file1.read())
	1/0 # 常规逻辑错误

以下干货来自群内大佬的教诲:

  1. finally内的代码不管有无异常发生,都会执行,这是基础和前提
  2. 如果没有异常发生,在try内的代码执行结束后执行else和finally(如果有else和finally的前提下),这是基础
  3. 如果有异常发生且被except捕获,那么执行except和finally(如果有finally的前提下),这是基础
  4. try…except…finally语法中,except不是必需的,也就是可以只有try…finally…
  5. 如果有异常发生但没被捕获,并且有finally,即try…finally…语句。由于finally它一般用于释放资源,如数据库连接、文件流等,虽然有报错,但是为了完整释放资源,finally还暂时不会返回ERROR,所以如果此时有return直接退出函数,那么错误就来不及被接收,相当于(我个人理解)是在错误被呈现之前直接退出函数(由于finally中return的存在),当然如果finally中没有return,那么就走正常的报错流程。
  6. 如果try和except和finally语句中都有return,实际只会返回finally中的返回值,finally中有return不仅会覆盖try和except内的返回值,还会掩盖try和except内的异常,就像异常没有发生一样

最后贴一段小代码,以助记忆

def test():
	print('start..')
	try:
		1/0
		return 'TRY RETURN'
	except Exception as e:
		print('ERROR')
		return 'EXCEPT RETURN'
	else:
		pass
	finally:
		print('end')
		return 'FINALLY RETURN'
if __name__ == '__main__':
	print(test())
# start..
# ERROR
# end
# FINALLY RETURN'
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值