实现了上下文协议的对象使用with语句
上下文管理器
1. __enter__ __exit__
的简单使用
class ContextTest(object):
def __init__(self):
self.my_dict = dict()
def __enter__(self):
self.my_dict["name"] = "Stone"
def __exit__(self, exc_type, exc_val, exc_tb):
self.my_dict.pop("name")
my_context = ContextTest()
with my_context:
print "In with context name: %s " % my_context.my_dict.get("name")
print "Out with context name: %s " % my_context.my_dict.get("name")
执行输入结果
In with context name: Stone
Out with context name: None
2. __enter__
返回值即为with后面as的值(当然也可以为一个对象)
例1
class ContextTest(object):
def __init__(self):
self.my_dict = dict()
def __enter__(self):
print "Add name to my_dict"
self.my_dict["name"] = "Stone"
return self.my_dict["name"]
def __exit__(self, exc_type, exc_val, exc_tb):
self.my_dict.pop("name")
print "Remove name of my_dict"
my_context = ContextTest()
with my_context as ret:
print "In with context name: %s , ret is: %s" % (my_context.my_dict.get("name"), ret)
print "Out with context name: %s " % my_context.my_dict.get("name")
运行输入结果:
Add name to my_dict
In with context name: Stone , ret is: Stone
Remove name of my_dict
Out with context name: None
例2
class ContextTest(object):
def __init__(self):
self.my_dict = dict()
def __enter__(self):
print "Add name to my_dict"
self.my_dict["name"] = "Stone"
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.my_dict.pop("name")
print "Remove name of my_dict"
def query(self, query_key):
return self.my_dict.get(query_key)
my_context = ContextTest()
with my_context as q:
print "query name: %s " % q.query("name")
运行输入结果:
Add name to my_dict
query name: Stone
Remove name of my_dict
3. __exit__
返回值True/False(False: 发生异常时,会将异常抛出,True: 发生异常时,不会将异常抛出)
返回 False: 发生异常时,会将异常抛出
class ContextTest(object):
def __init__(self):
self.my_dict = dict()
def __enter__(self):
print "Add name to my_dict"
self.my_dict["name"] = "Stone"
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.my_dict.pop("name")
print "Remove name of my_dict"
print "exc_type is: %s, exc_val is: %s, exc_tb is: %s" % (exc_type, exc_val, exc_tb)
return False # return False如果发生异常时,会将异常抛出,return True如果发生异常时,不会将异常抛出
def query(self, query_key):
return self.my_dict.get(query_key)
try:
with ContextTest() as q:
1/0
print "query name: %s " % q.query("name")
except Exception as e:
print "Catch an Exception: %s" % e.message
运行输入结果:
Connected to pydev debugger (build 191.7479.30)
Add name to my_dict
Remove name of my_dict
exc_type is: <type 'exceptions.ZeroDivisionError'>, exc_val is: integer division or modulo by zero, exc_tb is: <traceback object at 0x1015553f8>
Catch an Exception: integer division or modulo by zero
返回True: 发生异常时,不会将异常抛出
class ContextTest(object):
def __init__(self):
self.my_dict = dict()
def __enter__(self):
print "Add name to my_dict"
self.my_dict["name"] = "Stone"
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.my_dict.pop("name")
print "Remove name of my_dict"
print "exc_type is: %s, exc_val is: %s, exc_tb is: %s" % (exc_type, exc_val, exc_tb)
return True # return False如果发生异常时,会将异常抛出,return True如果发生异常时,不会将异常抛出
def query(self, query_key):
return self.my_dict.get(query_key)
try:
with ContextTest() as q:
1/0
print "query name: %s " % q.query("name")
except Exception as e:
print "Catch an Exception: %s" % e.message
运行输入结果:
Add name to my_dict
Remove name of my_dict
exc_type is: <type 'exceptions.ZeroDivisionError'>, exc_val is: integer division or modulo by zero, exc_tb is: <traceback object at 0x1038f7368>
使用contextmanager 实现上下文
yield 上面的代码类似__enter__
, yield 后面 类似于 __enter__
return 的值( 可作为as 后面的变量),yield 下面的代码类型 __exit__
from contextlib import contextmanager
class MyResource(object):
def query(self):
print("query data")
@contextmanager
def context_my_resource():
print("connect to resource") # 类似__enter__
yield MyResource() # 类似于 __enter__ return 的值
print("close resource connection") # 类似于 __exit__
with context_my_resource() as r:
r.query()
运行结果:
connect to resource
query data
close resource connection