对于系统资源,如打开文件,数据库连接,socket等而言,应用程序打开这些资源并执行完业务逻辑之后,必须做的一件事就是要关闭(断开)该资源。
使用with关键字的方法更为简洁,它的实现原理是什么?这就涉及到上下文管理器,在任何实现了__enter__() 和__exit__()方法的对象都可称之为上下文管理器。
1. 以下实例代码,在Python中如何正确关闭一个文件为例使用with关键字
#Python中如何正确关闭一个文件
#普通版本
def test01():
f = open('3.txt','w')
f.write("0000")
f.close()
print("写入成功,3.txt")
print(f.closed)
test01()
#进阶版本
def test02():
f = open("2.txt", "w")
try:
f.write("1111")
print("写入成功,2.txt")
except Exception:
print("ERROR")
finally:
f.close()
print(f.closed)
test02()
#高级版本
def testwith():
with open("1.txt", 'w') as f:
f.write('2222')
print("写入成功,1.txt")
testwith()
2. 用类还原with的实现原理,即__enter__()和__exit__()方法实现
class Testwith(object):
def __init__(self,file_name,mode):
self.file_name = file_name
self.mode = mode
def __enter__(self):
self.f = open(self.file_name, self.mode)
return self.f
def __exit__(self, *args):
self.f.close()
with Testwith('4.txt', 'w') as f:
f.write('4444')
print("4.txt写入成功,4444")
'''
1、首先Testwith('4.txt','w')初始化实例对象
2、with会寻找类中是否有__enter__和__exit__,如有则调用__enter__函数
3、最后__enter__()方法返回资源对象,这里就是你将要打开的那个文件对象4.txt
4、__exit__()函数方法则处理一些清理工作
'''
3. 再看一个示例代码,通过with打开,观察执行结果的输入顺序,当我们with Foo() as foo时,此时会执行__enter__方法,即enter called,但在a = 1/0出现异常,with将会终止,此时就执行__exit__方法,就算无异常,当执行体被执行完成后,__exit__方法仍然执行一次。所以说with open('filename') as f:不用关闭文件的原因就是在__exit__方法中,存在关闭文件的 *** 作,with已经帮我们完成了这个 *** 作。
class Foo():
def __enter__(self):
print("enter called")
def __exit__(self, exc_type, exc_val, exc_tb):
print("exit called")
print("exc_type:%s" % exc_type)
print("exc_val:%s" % exc_val)
print("exc_tb:%s" % exc_tb)
with Foo() as foo:
print("hello world!")
a = 1/0
print("hello end")
#终端输出结果如下
Traceback (most recent call last):
File "C:/Users/coral/PycharmProjects/pythonProject/python with关键字04.py", line 13, in
a = 1/0
ZeroDivisionError: division by zero
enter called
hello world!
exit called
exc_type:
exc_val:division by zero
exc_tb:
4. 使用contextmanager装饰器,实现with功能
from contextlib import contextmanager
'''
1、Python中提供了一个contextmanager的装饰器,更进一步简化了上下文管理器的实现方式
2、通过yield将函数分割为两部分,yield之前的语句在__enter__方法中执行,yield之后的语句在__exit__方法中执行
3、紧跟在yield后面的值是函数的返回值!
'''
@contextmanager
def testwith(path, mode):
f = open(path, mode)
yield f
f.close()
with testwith('5.txt', 'w') as f:
f.write('55555')
print("5.txt写入成功,55555")
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)