python中的with语句

本文详细介绍了Python中with语句的使用方法及其背后的执行原理,包括如何通过自定义上下文管理器来实现资源的安全访问与释放,同时也介绍了Python标准库contextlib提供的便捷工具。

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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值