OpenStack Python知识(1):with函数使用
来源:互联网 发布:苹果预约软件 编辑:程序博客网 时间:2024/06/02 04:36
基于contextlib使用with
- contextlib介绍
contextlib是为了加强with语句,提供上下文机制的模块,它是通过Generator实现的。通过定义类以及写__enter__和__exit__来进行上下文管理虽然不难,但是很繁琐。contextlib中的contextmanager作为装饰器来提供一种针对函数级别的上下文管理机制。常用框架如下:,从而不需要独立定义__enter__()和__exit__函数。实例代码:
from contextlib import contextmanager@contextmanagerdef tag(name): print "<%s>" % name yield print "</%s>" % name>>> with tag("h1"):... print "foo"...<h1>foo</h1>
contextlib更多详细介绍请参考:https://docs.python.org/2/library/contextlib.html。
- openstack使用
python中使用with作用是自动释放资源,即使在使用过程中有异常抛出。常规使用with需要定义__enter__, __exit__函数。本文基于openstack使用with做一种补充。先上代码。
/nova/virt/libvirt/driver.py中开始创建虚机。其中一个过程是创建domain和network如下:
def _create_domain_and_network(self, context, xml, instance, network_info, disk_info, block_device_info=None, power_on=True, reboot=False, vifs_already_plugged=False): """Do required network setup and create domain.""" block_device_mapping = driver.block_device_info_get_mapping( block_device_info) image_meta = objects.ImageMeta.from_instance(instance) for vol in block_device_mapping: connection_info = vol['connection_info'] if (not reboot and 'data' in connection_info and 'volume_id' in connection_info['data']): volume_id = connection_info['data']['volume_id'] encryption = encryptors.get_encryption_metadata( context, self._volume_api, volume_id, connection_info) if encryption: encryptor = self._get_volume_encryptor(connection_info, encryption) encryptor.attach_volume(context, **encryption) timeout = CONF.vif_plugging_timeout if (self._conn_supports_start_paused and utils.is_neutron() and not vifs_already_plugged and power_on and timeout): events = self._get_neutron_events(network_info)#获取network-vif-plugged事件 else: events = [] pause = bool(events) guest = None try: with self.virtapi.wait_for_instance_event( instance, events, deadline=timeout, error_callback=self._neutron_failed_callback): self.plug_vifs(instance, network_info) self.firewall_driver.setup_basic_filtering(instance, network_info) self.firewall_driver.prepare_instance_filter(instance, network_info) with self._lxc_disk_handler(instance, image_meta, block_device_info, disk_info): guest = self._create_domain( xml, pause=pause, power_on=power_on) self.firewall_driver.apply_instance_filter(instance, network_info) except exception.VirtualInterfaceCreateException: # Neutron reported failure and we didn't swallow it, so # bail here with excutils.save_and_reraise_exception(): if guest: guest.poweroff() self.cleanup(context, instance, network_info=network_info, block_device_info=block_device_info) except eventlet.timeout.Timeout: # We never heard from Neutron LOG.warn(_LW('Timeout waiting for vif plugging callback for ' 'instance %(uuid)s'), {'uuid': instance.uuid}, instance=instance) if CONF.vif_plugging_is_fatal: if guest: guest.poweroff() self.cleanup(context, instance, network_info=network_info, block_device_info=block_device_info) raise exception.VirtualInterfaceCreateException() # Resume only if domain has been paused if pause: guest.resume() return guest
在此我们看到with后面跟的是一个函数,而非常规的with XXXX as XXXX. 看下wait_for_instance_event函数定义:
#被contextlib类函数封装 @contextlib.contextmanager def wait_for_instance_event(self, instance, event_names, deadline=300, error_callback=None): """Plan to wait for some events, run some code, then wait. This context manager will first create plans to wait for the provided event_names, yield, and then wait for all the scheduled events to complete. Note that this uses an eventlet.timeout.Timeout to bound the operation, so callers should be prepared to catch that failure and handle that situation appropriately. If the event is not received by the specified timeout deadline, eventlet.timeout.Timeout is raised. If the event is received but did not have a 'completed' status, a NovaException is raised. If an error_callback is provided, instead of raising an exception as detailed above for the failure case, the callback will be called with the event_name and instance, and can return True to continue waiting for the rest of the events, False to stop processing, or raise an exception which will bubble up to the waiter. :param instance: The instance for which an event is expected :param event_names: A list of event names. Each element can be a string event name or tuple of strings to indicate (name, tag). :param deadline: Maximum number of seconds we should wait for all of the specified events to arrive. :param error_callback: A function to be called if an event arrives """ if error_callback is None: error_callback = self._default_error_callback events = {} for event_name in event_names: if isinstance(event_name, tuple): name, tag = event_name event_name = objects.InstanceExternalEvent.make_key( name, tag) try: events[event_name] = ( self._compute.instance_events.prepare_for_instance_event( instance, event_name)) except exception.NovaException: error_callback(event_name, instance) # NOTE(danms): Don't wait for any of the events. They # should all be canceled and fired immediately below, # but don't stick around if not. deadline = 0 yield #请注意此处的yield with eventlet.timeout.Timeout(deadline): for event_name, event in events.items(): actual_event = event.wait() if actual_event.status == 'completed': continue decision = error_callback(event_name, instance) if decision is False: break
知道contextlib用法之后很容易理解此处代码含义,即生成事件,然后等待plug vif等操作之后等待事件,如果超时则发送eventlet.timeout.Timeout异常,捕获异常之后做相应处理。
0 0
- OpenStack Python知识(1):with函数使用
- 【OpenStack】使用Komodo远程调试python(OpenStack)
- python with as 使用
- python中函数参数知识
- python知识-函数式编程
- 【OpenStack】OpenStack网络知识片断
- 使用Komodo远程调试Python(OpenStack)
- python 中with的使用
- python with as 简单使用
- Python:with语句的使用
- python使用的零散知识
- opencontrail integration with openstack
- OpenStack网络知识片断
- OpenStack小知识
- openstack入门知识介绍
- OpenStack历史知识
- python知识小结1
- learn with python-第三章:函数
- HDU 5194 DZY Loves Balls (组合数学)
- Java8移除永久代
- Android: Sqlite基本操作
- php 模仿百度蜘蛛采取网页信息
- 冒泡排序
- OpenStack Python知识(1):with函数使用
- 不同的路径
- 范型程序设计——洗牌
- Web Service是什么-作者: 阮一峰
- 大、小根堆
- 垃圾收集算法
- Python爬虫第一步之获取网页源代码
- Class.isAssignableFrom(Class clz)方法 与 instanceof 关键字的区别
- 概念区分