python的with关键字及上下文管理器

来源:互联网 发布:js图片触摸缩放 编辑:程序博客网 时间:2024/06/01 09:50

with 语句作为 try/finally 编码范式的一种替代,用于对资源访问进行控制的场合。
with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。


with语句的语法:


<span style="font-family:Microsoft YaHei;font-size:12px;">with context_expression [as target(s)]:        with-body</span>

这里 context_expression 要返回一个上下文管理器对象,该对象并不赋值给 as 子句中的 target(s) ,如果指定了 as 子句的话,会将上下文管理器的 __enter__() 方法的返回值赋值给 target(s)。target(s) 可以是单个变量,或者由“()”括起来的元组(不能是仅仅由“,”分隔的变量列表,必须加“()”)。


自定义上下文管理器:

  • context_manager.__enter__() :进入上下文管理器的运行时上下文,在语句体执行前调用。with 语句将该方法的返回值赋值给 as 子句中的 target,如果指定了 as 子句的话
  • context_manager.__exit__(exc_type, exc_value, exc_traceback) :退出与上下文管理器相关的运行时上下文,返回一个布尔值表示是否对发生的异常进行处理。参数表示引起退出操作的异常,如果退出时没有发生异常,则3个参数都为None。如果发生异常,返回

    True 表示不处理异常,否则会在退出该方法后重新抛出异常以由 with 语句之外的代码逻辑进行处理。如果该方法内部产生异常,则会取代由 statement-body 中语句产生的异常。要处理异常时,不要显示重新抛出异常,即不能重新抛出通过参数传递进来的异常,只需要将返回值设置为 False 就可以了。之后,上下文管理代码会检测是否 __exit__() 失败来处理异常

<span style="font-family:Microsoft YaHei;font-size:12px;">class DummyResource:    def __init__(self, tag):            self.tag = tag            print 'Resource [%s]' % tag    def __enter__(self):            print '[Enter %s]: Allocate resource.' % self.tag            return self  # 可以返回不同的对象    def __exit__(self, exc_type, exc_value, exc_tb):            print '[Exit %s]: Free resource.' % self.tag            if exc_tb is None:                print '[Exit %s]: Exited without exception.' % self.tag            else:                print '[Exit %s]: Exited with exception raised.' % self.tag                return False   # 可以省略,缺省的None也是被看做是False</span>

<span style="font-family:Microsoft YaHei;font-size:12px;">with DummyResource('Normal'):        print '[with-body] Run without exceptions.'----------------------------------------------------Resource [Normal]    [Enter Normal]: Allocate resource.    [with-body] Run without exceptions.    [Exit Normal]: Free resource.    [Exit Normal]: Exited without exception.</span>
<span style="font-family:Microsoft YaHei;font-size:12px;">with DummyResource('With-Exception'):        print '[with-body] Run with exception.'        raise Exception        print '[with-body] Run with exception. Failed to finish statement-body!'--------------------------</span>
Resource [With-Exception] [Enter With-Exception]: Allocate resource. [with-body] Run with exception. [Exit With-Exception]: Free resource. [Exit With-Exception]: Exited with exception raised. Traceback (most recent call last): File "G:/demo", line 20, in <module> raise Exception Exception

可以看到,正常执行时会先执行完语句体 with-body,然后执行 __exit__() 方法释放资源。
with-body 中发生异常时with-body 并没有执行完,但资源会保证被释放掉,同时产生的异常由 with 语句之外的代码逻辑来捕获处理。


参考链接:http://www.ibm.com/developerworks/cn/opensource/os-cn-pythonwith/




0 0
原创粉丝点击