OpenStack源码中的with分析
来源:互联网 发布:2016淘宝怎么开店步骤 编辑:程序博客网 时间:2024/06/15 08:50
作为个人学习笔记分享,有任何问题欢迎交流!
在OpenStack的源码中经常会看到一个语法:with,如下面的函数实现的是释放已经分配给实例的网络端口,其中就用到了with。
def _try_deallocate_network(self, context, instance, requested_networks=None): try: # tear down allocated network structure self._deallocate_network(context, instance, requested_networks) except Exception: with excutils.save_and_reraise_exception(): LOG.error(_('Failed to deallocate network for instance.'), instance=instance) self._set_instance_error_state(context, instance['uuid'])
在Exception下面有with excutils.save_and_reraise_exception(),从字面意思来看excutils.save_and_reraise_exception()很容易理解,
就是保存并重新抛出一个异常,这个功能的作用是,当有异常发生时,先针对这个异常进行一些必要的处理,而不是马上
向上抛出异常,即先保存异常,执行完下面的语句后,再抛出exception。
LOG.error(_('Failed to deallocate network for instance.'), instance=instance) self._set_instance_error_state(context, instance['uuid']) <span style="white-space:pre"></span>#在日志中记录一个错误信息:Failed to deallocate network for instance;设置实例的状态为error
那么这个功能是怎么实现的呢? 我们可以在nova/openstack/common/excutils.py中找到实现它的源码,注释也很清楚的描述了
这个类的功能。
class save_and_reraise_exception(object): """Save current exception, run some code and then re-raise. In some cases the exception context can be cleared, resulting in None being attempted to be re-raised after an exception handler is run. This can happen when eventlet switches greenthreads or when running an exception handler, code raises and catches an exception. In both cases the exception context will be cleared. To work around this, we save the exception state, run handler code, and then re-raise the original exception. If another exception occurs, the saved exception is logged and the new exception is re-raised. In some cases the caller may not want to re-raise the exception, and for those circumstances this context provides a reraise flag that can be used to suppress the exception. For example: except Exception: with save_and_reraise_exception() as ctxt: decide_if_need_reraise() if not should_be_reraised: ctxt.reraise = False """ def .__init__(self): self.reraise = True def __enter__(self): # 进入这个类做的处理,exc_info()获取当前正在处理的异常类的信息,是一个tuple: (type, value/message, traceback),参见[1] self.type_, self.value, self.tb, = sys.exc_info() return self def __exit__(self, exc_type, exc_val, exc_tb): #从这个类出去时的动作,如果发生异常,则输出异常并返回False, #如果reraise为True, 则重新抛出异常 if exc_type is not None: logging.error(_('Original exception being dropped: %s'), traceback.format_exception(self.type_, self.value, self.tb)) return False if self.reraise: #six是一个为python2和python3提供兼容性的库,six.reraise参见[2] six.reraise(self.type_, self.value, self.tb)
那么with在上述例子中扮演了一个什么角色呢?原来当执行到With其后的对象时,就返回该对象的__enter__(),当with后面的代码执行完毕后,
再返回该对象的__exit__(),参见[3],从而实现了先保存异常,做清理工作,再抛出异常这样的功能。
参考资料:
[1] https://docs.python.org/2/library/sys.html
[2] https://pythonhosted.org/six/
[3] http://sdqali.in/blog/2012/07/09/understanding-pythons-with/
0 0
- OpenStack源码中的with分析
- 【OpenStack源码分析之七】openstack中的RPC请求分析
- openstack nova 源码分析
- OpenStack Heat 源码分析
- OpenStack HeatClient 源码分析
- OpenStack Nova 源码分析
- OpenStack中的Heat分析
- OpenStack中的Heat分析
- 【OpenStack源码分析之一】初探OpenStack
- openstack G版源码分析
- OpenStack源码分析之live_migration
- OpenStack Cinder源码分析之一
- OpenStack源码分析之live_migration
- OpenStack Kolla 源码分析 --Ansible
- openstack-horizon/novaclient源码分析
- 【OpenStack源码分析之二】RabbitMQ分析
- openstack:nova中的几个问题分析
- OpenStack 中的baremetal组件分析
- CF7C 扩展欧几里得解不定方程
- 重构改善既有代码的设计--重新组织函数
- --图像旋转--
- 天天用的开发环境,你真的了解吗?
- 连锁便利店线上线下双向合璧
- OpenStack源码中的with分析
- uint8_t / uint16_t / uint32_t /uint64_t 是什么数据类型 - 大总结,看完全明白了
- 感觉有点烦躁
- zoj 3789 并查集
- HDOJ1521
- 【Leetcode】寻找数串中连续最大整数和且最大长度的子串
- 史上最短小精悍的javascript编写的俄罗斯方块游戏,仅仅60行代码 点赞
- Struts2常量详解
- POJ 1679 判断最小树是否唯一