python中的with语句

python中的with语句使用于对资源进行访问的场合,保证不管处理过程中是否发生错误或者异常都会执行规定的__exit__(“清理”)操作,释放被访问的资源,比如有文件读写后自动关闭、线程中锁的自动获取和释放等。

与python中with语句有关的概念有:上下文管理协议、上下文管理器、运行时上下文、上下文表达式、处理资源的代码段。

with语句的语法格式如下:

with context_expression [as target(s)]:
    with-body

with语句的执行原理:

context_manager=context_expression
exit=type(context_manager).__exit__
value=type(context_manager).__enter__(context_manager)
exc=True
try:
    try:
        targer=value
        with-body
    except:
        exc=False
        if not exit(context_manager, *sys.exc_info()):
            raise
finally:
    if exc:
        exit(context_manager,None,None,None)

从with的执行原理中可以看出,context_expression返回的对象中必须具有__exit__和__enter__两个方法,而且先检查__exit__方法在检查__enter__方法。无论在执行with-body中的函数体的过程中是否会发生异常,都会执行__exit__函数,如果没有异常,退出函数的中参数都为None;如果发生异常,则使用sys.exc_info()返回的异常信息为参数退出,并且当__exit__方法返回True时,忽略异常,当__exit__方法返回False时,抛出异常,此时,__exit__函数中就不需要再抛出异常,只需要将__exit__函数的返回值设为False就可以了。

例子:

 自定义支持上下文管理协议的类:

不抛出异常的函数体:

抛出异常的函数体:

python提供了contextlib模块,省去了写__enter__和__exit__重复工作了。contextlib模块提供了3个对象:contextmanager装饰器、上下文管理器closing和nested函数。

装饰器contextmanager用来对生成器函数进行装饰,生成器函数被装饰以后,返回的是一个上下文管理器。

 

  yield语句之前的代码在__enter__函数中执行,yield语句之后的代码在__exit__函数中执行。

closing上下文管理器包装起来的对象必须提供close()方法。

  closing的执行原理如下:

class closing(object):
    def __init__(self,thing):
        self.thing = thing
    def __enter__(self):
        return self.thing
    def __exit__(self, *exc_info):
        self.thing.close()

  因此,closing上下文管理器包装的对象必须提供close()函数。

nested函数可以将多个上下文管理器组织在一起,避免使用嵌套的with语句。  

with nested(A(),B(),C()) as (X,Y,Z):
    with-body

类似于:

with A() as X:
    with B() as Y:
        with C() as Z:
            with-body
原文地址:https://www.cnblogs.com/xinyuefeiyang/p/7237249.html