python 提供了with语法用于简化资源操作的后续清除操作,实现原理建立在上下文管理器协议(实现__enter__和__exit__)之上。
上下文管理器:上下文管理器的本质就是能够支持with操作。任何实现了__enter__()和__exit__() 方法的对象都可以成为上下文管理器。
常见的文件对象就是实现了上下文管理器。
实现上下文管理器, 写一个自己的文件类
class MyFile(object):
"""支持上下文管理器的类"""
def __init__(self, file_name, file_mode):
"""构造实例对象"""
self.name = file_name
self.mode = file_mode
def __enter__(self):
"""上文 提供资源"""
print("进入上文 获取资源")
self.temp_file = open(self.name, self.mode)
return self.temp_file
def __exit__(self, exc_type, exc_val, exc_tb):
"""下文 提供资源关闭的方法"""
print("进入下文 关闭资源")
self.temp_file.close()
with MyFile("1.txt", "rb") as file:
file_data = file.read(20)
print("正在使用资源 数据为:%s" % file_data)
进入上文 获取资源
正在使用资源 数据为:b'context manager'
进入下文 关闭资源
1 o = MyFile()创建一个实例对象o
2 调用实例对象o 上文-方法__enter__ 获取资源 将资源赋值给file
3 调用file执行操作
4 调用实例对象o 下文-方法__exit__ 关闭刚刚使用的资源file
__exit__(self, exc_type, exc_val, exc_tb)
exc_type代表异常类型,exc_value代表异常信息, exc_tb代表异常栈的跟踪信息(是一个异常对象 <traceback object at 0x0000021D44E91B48>)。
with执行体正常执行时,三者的值为None。
当with执行体出现异常时,三个参数会接受异常的信息,__exit__()方法会执行完,关闭文件。异常信息需要处理不然会抛出异常,所以要在with执行体内加入try-except进行捕获。
实现上下文管理器
Python 还提供了一个 contextmanager 的装饰器,更进一步简化了上下文管理器的实现方式。通过 yield 将函数分割成两部分,yield 之前的语句在 __enter__ 方法中执行,yield 之后的语句在 __exit__ 方法中执行。紧跟在 yield 后面的值是函数的返回值。
- from contextlib import contextmanager
- @contextmanager
- yield
from contextlib import contextmanager
@contextmanager
def myopen(name, mode):
"""提供上文 和 下文"""
# 上文
print("进入上文 获取资源")
tfile = open(name, mode)
yield tfile
# 下文
print("进入下文 关闭资源")
tfile.close()
with myopen("1.txt", "rb") as file:
file_data = file.read(20)
print("正在使用资源 数据为:%s" % file_data)
进入上文 获取资源
正在使用资源 数据为:b'context manager'
进入下文 关闭资源