python中with关键字和上下文管理器

一、文件操作中使用with

当“with” 执行的时候,Python 会调用相应的 __enter__方法并且把返回的值赋值给as 后面的变量。出现异常或正常执行都会调用__exit__  方法

with后是一个对象:

with  对象(实现了__enter__和__exit__  方法方法的类)  as   变量(__enter__返回值会赋给此变量

class Demo:
    def __enter__(self):
        return 'hello'
    def __exit__(self, exc_type, exc_val, exc_tb):
        pass
with Demo() as d:
    print(d)

由于读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所以,为了保证无论是否出错都能正确的关闭文件,我们先使用try… finally来实现

使用try … finally:使用这种方式,无论如何最后文件都会关闭,解决了上述问题,但是代码比较繁琐,我们思考有没有简单的方式

try:
	# 1.以读的方式打开文件
	f = open('1.txt','r')
	# 2.进行文件操作
	f.write('xxxxx') # 这一步会引发异常

except IOError as e:
	print("文件操作出错",e)

finally:
	f.close()
class controlled_execution:
    def __enter__(self):
        set things up
        return thing
    def __exit__(self, type, value, traceback):
        tear things down
 
with controlled_execution() as thing:
     some code

当“with” 执行的时候,Python 会调用相应的 __enter__方法并且把返回的值赋值给as 后面的变量。Python会执行with下面的“some code”并且不管“some code”中发生了什么都会调用 __exit__  方法。

另外__exit__方法还可以处理异常如返回一个正确的值,例如:

def __exit__(self, type, value, traceback):
        return isinstance(value, TypeError)

使用 with 关键字:这种方式,当文件发生异常时,文件将自动关闭。将f贴给open的返回值,当离开with代码块时,系统可以自动调用f.close()方法,那么它的实现原理是什么值得研究?为了研究这种方式,先需要学习什么是上下文管理器:

1、 上下文管理器

首先先要理解上下文。这个要怎么理解呢,很抽象,拿文件操作举例,打开文件就相当于上文,操作文件就相当于文中,关闭文件就相当于下文

上下文管理器:上下文管理器本质就是能够支持with操作的类或对象。任何实现了__ enter __ ()和__ exit __()方法的类对象对可以称之为上下文管理器。上下文管理器对象可以使用with关键字对上下文管理,显然,文件(file对象)也实现了上下文管理协议(上面的两个方法)
 

class MyFile():
	# 1. __init__()  初始化方法
	def __init__(self,file_name,file_mode):
		self.file_name = file_name
		self.file_mode = file_mode
		
	# 2. __enter__() 上文方法
	def __enter__(self):
		print("进入上文")
		self.file = open(self.file_name,self.file_mode)
		return self.file
	
	# 3. __exit__() 下文方法
	def __exit__():
		print("进入下文")
		self.file.close()

# hello.txt为自己定义的文件
# file 并不是MyFile的一个对象,而是上文__enter__函数返回的内容,是一种资源

with MyFile('hello.txt','r') as file:
	file_data = file.read()
	print(file_data)

# result

进入上文
这里是你文件里的内容
进入下文
			

2、使用装饰器实现管理上下文 

通过装饰器@ contextmanager实现上下文管理:

  • 导入模块:from contextlib import contextmanager
  • @contextmanager
    def myopen(file_name,file_mode):
from contextlib import contextmanager

@contextmanager
def myopen(file_name,file_mode):
	print("进入上文")
	# 1.打开资源
	file = open(file_name,file_mode)
	# 2.返回资源
	yield file
	print("进入下文")
	# 3.关闭资源
	file.close()

with myopen('hello.txt','r') as file:
	file_data = file.read()
	print(file_data)

当然很多人会有疑问,装饰器contextmanager的作用是什么,他就是把enter和exit函数装饰给了myopen函数,使得文件资源得以自动打开退出(如果你进入该装饰器的源码可以看到里边实现了enter和exit函数)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值