python之with...as...以及在openstack中的应用详解

with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的清理工作,来释放资源,比如文件使用后自动关闭,县城中锁的自动获取和释放等。

 

with相关的术语:

要是用with语句,首先要明白上下文管理器这一概念。有了上下文管理器,with语句才能工作。

下面是一组与上下文管理器和with语句相关的概念。

上下文管理协议(Context Managerment Protocol):包含enter()和exit()方法,支持该协议的对象要实现这两个方法。

上下文管理器(Context Manager):支持上下文管理协议的对象,这种对象实现了enter()和exit()方法。上下文管理器定义执行with语句时要建立的运行时上下文,负责执行with语句块上下文中的进入与退出操作。通常使用with语句调用上下文管理器,也可以通过直接调用其方法来使用。

运行时上下文(runtime context):由上下文管理器创建,通过上下文管理器的enter()和exit()方法实现,enter()方法在语句执行之前进入运行时上下文,exit()在语句体执行完后从运行时上下文退出。with语句支持运行时上下文这一概念。

上下文表达式(context Expression):with语句中跟在关键字with之后的表达式,该表达式要返回一个上下文管理器对象。

语句体(with-body):with语句包裹起来的代码块,在执行语句之前会调用上下文管理器的enter()方法,执行完语句体之后会执行exit()方法。

基本语法和工作原理:

with语句的语法格式如下:

1. with语句的语法格式

with context_expression [as target(s)]:

           with-body

这里context expression要返回一个上下文管理器对象,该对象并不赋值给as子语句中的target,如果指定了as子句的话,会将上下文管理器中的_enter()方法的返回值赋值给target.

target可以是单个变量,或者由"()"括起来的元组(不能是仅仅由“,”分割的变量列表,必须加“()”)

 

在oslo_utils中的timeutils中的应用

在\nova\nova\compute\manager.py

from oslo_utils import timeutils

在manager.py中使用timeutils的例子如下:

            with timeutils.StopWatch() as timer:
                self._build_and_run_instance(context, instance, image,
                        decoded_files, admin_password, requested_networks,
                        security_groups, block_device_mapping, node, limits,
                        filter_properties, request_spec, accel_uuids)
            LOG.info('Took %0.2f seconds to build instance.',
                     timer.elapsed(), instance=instance)

   这里通过timer.elapsed()来显示timeutils.StopWatch()到LOG.info之间的时间

oslo_utils中的StopWatch的实现如下:

https://github.com/openstack/oslo.utils/blob/master/oslo_utils/timeutils.py

class StopWatch(object):
    _STARTED = 'STARTED'
    _STOPPED = 'STOPPED'
    
    def __init__(self, duration = None):
        if duration is not None and duration < 0:
            raise ValueError()

        self._duration = duration
        self._started_at = None
        self._stopped_at = None
        self._state = None
        self._split = ()
#开始计数
    def start(self):
        if self._state == self._STARTED:
            return self

        self._started_at = now()
        self._stopped_at = None
        #当前状态设置为_Started
        self._state = self._STARTED
        self._splits = ()

    @staticmethod
    def _delta_seconds(earlier, later):
        return max(0, later - earlier)

    def elapsed(self, maximum = None)
        if self._state not in (self._STARTED, self._STOPPED):
                raise()
        if self._state == self._STOPPED:
            elapsed = self._delta_seconds(self._started_at, self._stopped_at)
        else:
            elapsed = self._delta_seconds(self._started_at, now())
        if maximum is not None and elapsed > maximum:
            elapsed = max(0.0, maximum)
        return elapsed
        
#通过with 调用StopWatch的时候,会自动调用__enter__,在__enter__ 中有会调用start 来开始计数
    def __enter__(self):
        """Starts the watch."""
        self.start()
        return self

StopWatch 这个class 有实现__enter__,因此当在with 中调用StopWatch 是会自动调用__enter__,在__enter__ 中有会调用自身的start函数 来记录下当前的时间,当前时间是通过now函数获得,并把时间记录到内部变量_started_at中这样当用户下次在主动调用elapsed的时候就会主动 通过now函数得到当前的时间减去之前记录在_started_at的时间.

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值