为了让一个对象兼容 with
语句,你需要实现 __enter__()
和 __exit__()
方法,上下文管理器是个对象,它有__enter__
和__exit__
两个方法
demo1:使用 __enter__()
和 __exit__()
方法
class Context():
def __enter__(self):
print('start...')
def __exit__(self, exc_type, exc_val, exc_tb):
print('end')
with Context():
print('上下文管理器')
运行结果为:
start...
上下文管理器
end
注意:
1.在离开上下文时,解释器会给__exit__
额外传递3个位置参数。这些参数都是用于处理上下文中的异常的,所以正常状态下,他们都是None
2.exit的三个参数表示:
# (<class 'Exception'>,
# Exception('Raised',),
# <traceback object at 0x0000025A35441D88>)
- 异常类型;
- 异常对象(关于
repr
将在字符串系列中详细说明); - 栈对象;
demo2:实现一个全新的上下文管理器
from contextlib import contextmanager
直接使用@contextmanager去装饰函数即可
分析:
通常情况下,如果要写一个上下文管理器,你需要定义一个类,里面包含一个 __enter__()
和一个__exit__()
方法,如下所示:
import time
class timethis:
def __init__(self, label):
self.label = label
def __enter__(self):
self.start = time.time()
def __exit__(self, exc_ty, exc_val, exc_tb):
end = time.time()
print('{}: {}'.format(self.label, end - self.start))
尽管这个也不难写,但是相比较写一个简单的使用 @contextmanager
注解的函数而言还是稍显乏味
@contextmanager
应该仅仅用来写自包含的上下文管理函数。 如果你有一些对象(比如一个文件、网络连接或锁),需要支持 with
语句,那么你就需要单独实现 __enter__()
方法和 __exit__()
方法