python上下文管理器
背景知识:
对于系统的资源,例如文件,数据库连接,socket等而言,应用程序打开这些资源使用,使用完成后必须要做的一件事情就是关闭或者断开连接。因为操作系统分配给我们的资源连接都是有上限的,长时间不关闭有可能会抛出异常。
例如:
文件资源长期不关闭,有可能会出现‘Too nany open files’的错误。
数据库长期不关闭,有可能会出现‘Can not connect Mysql Server Too many connections’的错误
来看看如何关闭文件资源:
普通版:
def m1(): f = open('output.txt', 'w') # 如果write的过程中出现了错误,程序没有办法close f.write('张飞龙') f.close()
改良版:
def m2(): f = open('output.txt', 'w') # 使用try try: f.write('张飞龙') except IOError: print('oops error') finally: f.close()
高级版
def m3(): with open('output.txt', 'r') as f: f.write('张飞龙')
open的方法返回值赋值给变量f,当离开with代码块的时候,系统会自动调用f.close()方法,那么他的实现原理是什么?在讲with的原理前要涉及到另外一个概念,就是上下文管理器(context manager)
概念:
实现了上下文协议的对象即为上下文管理器。
上下文协议:__enter__,__exit__
作用:用于资源的获取和释放。
使用上下文管理器:
class File(): def __init__(self, filename, mode): self.filename = filename self.mode = mode def __enter__(self): '__enter__方法返回资源对象' print('begin entering') self.f = open(self.filename, self.mode) return self.f def __exit__(self, *args): '''__exit__方法处理一些清理工作''' print('will exit') self.f.close() # 因为File类实现了上下文管理器,所以现在就可以使用with语句了 with File('output.txt', 'w') as f: print('writing') f.write('hello,张飞龙')
begin entering
writing
will exit
使用contextmanager装饰器实现:
from contextlib import contextmanager @contextmanager def my_open(path, mode): f = open(path, mode) yield f f.close() with my_open('output.txt', 'w') as f: f.write('hello, the simplest context manager')
总结:
python提供了with语法用于简化资源操作的后续清楚操作,是try/finally的替代方法,实现原理建立在上下文管理器之上,此外,python还提供了一个contextmanager装饰器,更进一步简化上下管理器的实现方式。