python with语句与上下文管理器

经常我们在设计API的时候会有这样的需求:

(1)用户从某个管理器中获取一个资源

(2)用户使用这个资源

(3)在使用完之后,需要将这个资源还给管理器


一般情况下,我们需要做两个接口:

get,和return

这样子有一种风险就是,在写业务代码的时候,忘记了将资源还回去。。。


但是对于python而言,由于加上了上下文管理,就可以避免这种问题。。。而且对于API的设计而言,也更加的鲁棒。。。


也就是我们常见的with语句:

context_manager = context_expression
    exit = type(context_manager).__exit__  
    value = type(context_manager).__enter__(context_manager)
    exc = True   # True 表示正常执行,即便有异常也忽略;False 表示重新抛出异常,需要对异常进行处理
    try:
        try:
            target = value  # 如果使用了 as 子句
            with-body     # 执行 with-body
        except:
            # 执行过程中有异常发生
            exc = False
            # 如果 __exit__ 返回 True,则异常被忽略;如果返回 False,则重新抛出异常
            # 由外层代码对异常进行处理
            if not exit(context_manager, *sys.exc_info()):
                raise
    finally:
        # 正常退出,或者通过 statement-body 中的 break/continue/return 语句退出
        # 或者忽略异常退出
        if exc:
            exit(context_manager, None, None, None) 
        # 缺省返回 None,None 在布尔上下文中看做是 False


上面就是with语句的执行流程,大体分为如下几个步骤:

(1)获取上下文管理器

(2)获取管理器的exit和enter方法

(3)调用enter方法,然后获取一个值,如果调用with的地方有as语句的话,需要进行赋值

(4)执行with语句的body部分代码

(5)检查异常,如果正常的话,调用exit。。。


其实,也就是python的with语句的执行为我们做好了这些上下文的管理。。。。


前面都说了一大堆的介绍,那么看一下该如何创建支持上下文管理的方法吧:

#-*-coding:utf-8-*-
__author__ = 'fjs'

import contextlib

@contextlib.contextmanager
def test():
    try:
        yield 1
    except:
        print "ooo"
        raise
    else:
        print "ok"


try:
    with test() as fjs:
        print fjs
except:
    print "error"


这里的关键是使用了上面的额注解。。。利用了python给好的工具。。。

其实这里还可以看到,定义的方法其实是一个生成器。。。这样,在yield返回之后,就可以做资源的回收工作了。。。嗯。。。还是挺好用的。。以后在设计API的时候就应该果断的用上。。。



@contextlib.contextmanager

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值