https://docs.python.org/3.7/library/
参考书:Python参考手册+第4版_修订版
--------------------------------------------------------------------------
1.自定义上下文管理器
定义:
class list_withFun(object):
def__init__(self,lst):
self.lst=lst
def__enter__(self):
self.old_data=list(self.lst)
return self.old_data
def__exit__(self,type,value,trackback):
if type is None:
self.lst[:]=self.old_data
return True
调用1:
items=[1,2,3]
with list_withFun(items) as s:
s.append(4)
s.append(5)
print(items)
调用2
try:
with list_withFun(items) as s:
s.append(6)
s.append(7)
raise RuntimeError('we are hosed')
print('error')
except RuntimeError:
pass
print(items)
##
***********************************************************
定义:
from contextlib import contextmanager
@contextmanager
def list_withFun1(lst):
old_data=list(lst) #yield 语句前:初始化资源
yield old_data #返回值
lst[:]=old_data #yield 语句后:释放资源,处理异常
调用
items=[11,12,13]
with list_withFun(items) as s:
s.append(14)
s.append(15)
print(items)
------------------------------------------------------------------------------
2.应用
with 语句适用对资源访问场合(上下文管理器对象),确保不管使用过程中是否发生
异常都执行清理,释放资源,如文件用后自动关闭、线程中锁自动获取和释放等。
对象有:
file;decimal.Context;thread.LockType;threading.Lock;threading.Rlock;
threading.Condition;threading.Semaphore;threading.BoundedSemaphore
------------------------------------------------------------------------------
3.1.语法格式:
contextmanager.__enter__()
输入运行时此方法返回的值绑定到使用此上下文管理器as的with语句子句中的标识符。
contextmanager.__exit__(exc_type,exc_val,exc_tb )
退出运行返回bool,是否抑制发生异常。True异常忽略;False重新抛出异常
执行with语句正文发生异常,参数包含异常类型,值和追溯信息或3个None。
withcontext_expression [as target(s)]:
with-body
参数:
context_expression 要返回一个上下文管理器对象;
__enter__() 方法的返回值赋值给 target(s)。target(s) 是单变量,或者由“()”括起来的元组
------------------------------------------------------------------------------
3.2.example
文件操作:
with open(r'somefileName') as somefile:
for line in somefile:
print line
# ...more code
try/finally 操作文件
somefile = open(r'somefileName')
try:
for line in somefile:
print line
# ...more code
finally:
somefile.close()
-------------------------------------------------------------------------------
定义:
class A(object):
def __enter__(self):
print('__enter__()called')
return self
def print_hello(self):
print("helloworld!")
def __exit__(self, e_t,e_v, t_b):
print('__exit__()called')
调用:
with A() as a: # a为__enter__的返回对象
a.print_hello()
print('got instance')
输出:
__enter__() called
hello world!
got instance
__exit__() called
-------------------------------------------------------------------------------
4.自定义上下文管理器contextlib模块
4.1.装饰器 contextmanager
生成器函数被装饰以后,返回的是一个上下文管理器
装饰器contextmanager 使用示例
from contextlib import contextmanager
@contextmanager
def demo():
print '[Allocateresources]' # yield 之前的语句在 __enter__() 方法中执行;资源分配
print 'Code beforeyield-statement executes in __enter__'
yield '*** contextmanagerdemo ***'#返回值
print 'Code afteryield-statement executes in __exit__'
print '[Free resources]' # yield 之后的语句在 __exit__() 中执行;资源释放
调用:
with demo() as value:
print 'Assigned Value: %s'% value
输出:
[Allocate resources]
Code beforeyield-statement executes in __enter__
Assigned Value: ***contextmanager demo ***
Code afteryield-statement executes in __exit__
[Free resources]
定义:
@contextmanager
def context():
print('entering the zone')
try:
yield
except Exception as e:
print('with an error%s'%e)
raise e
else:
print('with no error')
调用:
with context():
print('----in contextcall------')
输出:
entering the zone
----in contextcall------
with no error
-------------------------------------------------------------------------------
4.2.函数 nested可以将多个上下文管理器组织在一起,避免使用嵌套 with 语句。
with nested(A(), B(), C()) as (X, Y, Z):
# with-body code here
类似于:
with A() as X:
with B() as Y:
with C() as Z:
# with-body codehere
需要注意:
发生异常后,如果某个上下文管理器的 __exit__() 方法对异常处理返回 False,
则更外层的上下文管理器不会监测到异常。
-------------------------------------------------------------------------------
4.3.上下文管理器closing
适用提供close() 实现的对象如网络连接、数据库连接等,
可以在自定义类时通过接口 close() 来执行所需要的资源“清理”工作。
class closing(object):
# help doc here
def __init__(self,thing):
self.thing = thing
def __enter__(self):
return self.thing
def __exit__(self,*exc_info):
self.thing.close()
自定义支持 closing 的对象
class ClosingDemo(object):
def __init__(self):
self.acquire()
def acquire(self):
print 'Acquireresources.'
def free(self):
print 'Clean up anyresources acquired.'
def close(self):
self.free()
调用:
with closing(ClosingDemo()):
print 'Using resources'
输出:
Acquire resources.
Using resources
Clean up anyresources acquired.
-------------------------------------------------------------------------------