Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1268847
  • 博文数量: 389
  • 博客积分: 2874
  • 博客等级: 少校
  • 技术积分: 3577
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-24 10:34
文章分类

全部博文(389)

文章存档

2020年(2)

2018年(39)

2017年(27)

2016年(3)

2015年(55)

2014年(92)

2013年(54)

2012年(53)

2011年(64)

分类: Python/Ruby

2017-10-27 10:51:10

源码是这样的:

点击(此处)折叠或打开

  1. with self.virtapi.wait_for_instance_event( #错误位置
  2.                     instance, events, deadline=timeout,
  3.                     error_callback=self._neutron_failed_callback):
  4.                 self.plug_vifs(instance, network_info) #添加虚拟网卡,后面是添加防火墙
  5.                 self.firewall_driver.setup_basic_filtering(instance,
  6.                                                            network_info)
  7.                 self.firewall_driver.prepare_instance_filter(instance,
  8.                                                              network_info)
  9.                 with self._lxc_disk_handler(instance, instance.image_meta,
  10.                                             block_device_info, disk_info):
  11.                     guest = self._create_domain(
  12.                         xml, pause=pause, power_on=power_on,
  13.                         post_xml_callback=post_xml_callback)

  14.                 self.firewall_driver.apply_instance_filter(instance,
  15.                                                            network_info)
with后面类必须要有一个__enter__()函数和一个__exit__()函数,然后看代码wait_for_instance_event,发现里面有yield,很奇怪。

点击(此处)折叠或打开

  1. @contextlib.contextmanager
  2.     def wait_for_instance_event(self, instance, event_names, deadline=300,
  3.                                 error_callback=None):
  4.         a
  5.         yield
  6.         b
这里解决 with和yield问题的是contextlib.contextmanager这个装饰器

点击(此处)折叠或打开

  1. @contextlib.contextmanager
  2.     def wait_for_instance_event(self, instance, event_names, deadline=300,
  3.                                 error_callback=None):
  4.         a
  5.         yield
  6.         b
contextmanager代码里有较详细的注释:

点击(此处)折叠或打开

  1. def contextmanager(func):
  2.     """@contextmanager decorator.

  3.     Typical usage:

  4.         @contextmanager
  5.         def some_generator():
  6.             
  7.             try:
  8.                 yield
  9.             finally:
  10.                 

  11.     This makes this:

  12.         with some_generator() as :
  13.             

  14.     equivalent to this:              下面是实际的代码执行流程

  15.         
  16.         try:
  17.              =
  18.                             with的body部分在这里执行
  19.         finally:
  20.             

  21.     """
  22.     @wraps(func)
  23.     def helper(*args, **kwds):
  24.         return GeneratorContextManager(func(*args, **kwds))
  25.     return helper

contextmanager是通过GeneratorContextManager实现的,GeneratorContextManager实现了__enter__和__exit__,这两个函数都调了next()函数来结合yield。

点击(此处)折叠或打开

  1. class GeneratorContextManager(object):
  2.     """Helper for @contextmanager decorator."""

  3.     def __init__(self, gen):
  4.         self.gen = gen

  5.     def __enter__(self):
  6.         try:
  7.             return self.gen.next()
  8.         except StopIteration:
  9.             raise RuntimeError("generator didn't yield")

  10.     def __exit__(self, type, value, traceback):
  11.         if type is None:
  12.             try:
  13.                 self.gen.next()
  14.             except StopIteration:
  15.                 return
  16.             else:
  17.                 raise RuntimeError("generator didn't stop")
  18.         else:
  19.             if value is None:
  20.                 # Need to force instantiation so we can reliably
  21.                 # tell if we get the same exception back
  22.                 value = type()
  23.             try:
  24.                 self.gen.throw(type, value, traceback)
  25.                 raise RuntimeError("generator didn't stop after throw()")
  26.             except StopIteration, exc:
  27.                 # Suppress the exception *unless* it's the same exception that
  28.                 # was passed to throw(). This prevents a StopIteration
  29.                 # raised inside the "with" statement from being suppressed
  30.                 return exc is not value
  31.             except:
  32.                 # only re-raise if it's *not* the exception that was
  33.                 # passed to throw(), because __exit__() must not raise
  34.                 # an exception unless __exit__() itself failed. But throw()
  35.                 # has to raise the exception to signal propagation, so this
  36.                 # fixes the impedance mismatch between the throw() protocol
  37.                 # and the __exit__() protocol.
  38.                 #
  39.                 if sys.exc_info()[1] is not value:
  40.                     raise

灵活的python。
阅读(1506) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~