看着代码又发现了一个奇怪的东西:

    @contextlib.contextmanager
def __call__(self, incoming):
result_wrapper = [] yield lambda: result_wrapper.append(
self._dispatch_and_handle_error(incoming)) if result_wrapper[0] == NotificationResult.HANDLED:
incoming.acknowledge()
else:
incoming.requeue()

contextlib.contextmanager(func)

This function is a decorator that can be used to define a factory function for with statement context managers, without needing to create a class or separate __enter__() and __exit__() methods.

A simple example (this is not recommended as a real way of generating HTML!):

from contextlib import contextmanager

@contextmanager
def tag(name):
print "<%s>" % name
yield
print "</%s>" % name >>> with tag("h1"):
... print "foo"
...
<h1>
foo
</h1>

The function being decorated must return a generator-iterator when called. This iterator must yield exactly one value, which will be bound to the targets in the with statement’s as clause, if any.

At the point where the generator yields, the block nested in the with statement is executed. The generator is then resumed after the block is exited. If an unhandled exception occurs in the block, it is reraised inside the generator at the point where the yield occurred. Thus, you can use a try...except...finally statement to trap the error (if any), or ensure that some cleanup takes place. If an exception is trapped merely in order to log it or to perform some action (rather than to suppress it entirely), the generator must reraise that exception. Otherwise the generator context manager will indicate to the with statement that the exception has been handled, and execution will resume with the statement immediately following the with statement.

也就是说用了contextmanager装饰器的generator,yield语句之前的部分会在进入with的语句块之前执行(generator生成过程,generator函数开始到yield之间的部分),yield的值可以用于with中的as来定义个语句块内的变量。yield的值相当于是__enter__函数的返回,而yield语句后面部分将会在with语句块退出时执行,相当在__exit__函数中执行。

先来试验一下派森大法中generator的执行步骤:

>>> def FakeGenerator():
... print 'iteration begin'
... yield {"msg":'Hello'}
... print 'iteration end'
...
>>> for obj in FakeGenerator():
... print 'get msg:', obj['msg']
...
iteration begin
get msg: Hello
iteration end

也就是说每次迭代中FakeGenerator只会执行到yield语句,然后就获取yield返回的对象给for循环里的语句使用,等到下次迭代时再从yield后面的语句开始执行,真是吊炸天!这样就几乎实现了with语句中对象加了__enter__和__exit__方法时的功能。

不过每次要写个for来代替with显得太土,于是就有了我们的@contextmanager装饰器,它的实现或许是这样的

>>> class FakeGeneratorContext(object):
... def __init__(self, func):
... self.generator_func = func
... self.__exit__ = None
... self.__enter__= None
... self.generator = None
... def __enter__(self):
... self.generator = self.generator_func()
... return self.generator.next()
... def __exit__(self, ext, exv, tb):
... try:
... self.generator.next()
... except StopIteration:
... pass
>>> def fakecontext(func):
... def wrapper():
... context = FakeGeneratorContext(func)
... return context
... return wrapper
...
>>> @fakecontext
... def FakeGenerator():
... print 'iteration begin'
... yield {'msg':'Hello'}
... print 'iteration end'
...
>>> with FakeGenerator() as obj:
... print obj["msg"]
...
iteration begin
Hello
iteration end

有点烦了,再玩下去就和搞Java的一样了

Python contextlib.contextmanager的更多相关文章

  1. python 上下文管理器contextlib.ContextManager

    1 模块简介 在数年前,Python 2.5 加入了一个非常特殊的关键字,就是with.with语句允许开发者创建上下文管理器.什么是上下文管理器?上下文管理器就是允许你可以自动地开始和结束一些事情. ...

  2. Python.with.context-manager

    Context Manager 1. Context Manager简介 "Context managers are a way of allocating and releasing so ...

  3. python contextlib 上下文管理器

    1.with操作符 在python中读写文件,可能需要这样的代码 try-finally读写文件 file_text = None try: file_text = open('./text', 'r ...

  4. 源码剖析@contextlib.contextmanager

    示例 @contextlib.contextmanager def result(a): print('before') yield print('after') 外层装饰源码 包装func函数,真实 ...

  5. Python with/as和contextlib上下文管理使用说明

    with/as 使用open打开过文件的对with/as都已经非常熟悉,其实with/as是对try/finally的一种替代方案. 当某个对象支持一种称为"环境管理协议"的协议时 ...

  6. Python——with语句、context manager类型和contextlib库

    目录 一.with语句 二.上下文管理器 三.contextlib模块 基本概念 上下文管理协议(Context Management Protocol) 包含方法 __enter__() 和 __e ...

  7. Python——常用模块(time/datetime, random, os, shutil, json/pickcle, collections, hashlib/hmac, contextlib)

    1.time/datetime 这两个模块是与时间相关的模块,Python中通常用三种方式表示时间: #时间戳(timestamp):表示的是从1970年1月1日00:00:00开始按秒计算的偏移量. ...

  8. Python 上下文管理器模块--contextlib

    在 Python 处理文件的时候我们使用 with 关键词来进行文件的资源关闭,但是并不是只有文件操作才能使用 with 语句.今天就让我们一起学习 Python 中的上下文管理 contextlib ...

  9. python中关于with以及contextlib的使用

    一般在coding时,经常使用with来打开文件进行文件处理,然后无需执行close方法进行文件关闭. with open('test.py','r' as f: print(f.readline() ...

随机推荐

  1. Pycharm关闭后Python.exe还是在后台运行

    pycharm运行程序关闭后会弹出一个对话框: 一定要选择第一个,不然python.exe一直会在后台运行.

  2. Python3之json模块

    概念: 序列化(Serialization):将对象的状态信息转换为可以存储或可以通过网络传输的过程,传输的格式可以是JSON,XML等.反序列化就是从存储区域(JSON,XML)读取反序列化对象的状 ...

  3. python pika简单实现RabbitMQ通信

    Windows上安装及启动RabbitMQ https://blog.csdn.net/hzw19920329/article/details/53156015 安装python pika库 pip ...

  4. vue is detected

    Vue.js is detected on this page. Devtools inspection is not available because it's in production mod ...

  5. asp 文章内容里的图片宽度过大 撑爆页面布局 解决办法

    有时候帮朋友做做企业网站,还是asp+access来的快,也经济(不用开数据库空间),fck做的后台内容编辑功能,但是他们传图片的时候不靠谱,图片不管有多宽都直接up上来,把前台页面撑的是面目全非! ...

  6. 002 android studio 常用设置

    1.改变字体 file--->setting --->font--->size 2.更改最小安卓版本 在project目录下,app下的build.gradle中修改 注意:buil ...

  7. fluent中UDF环境变量问题的三种解决方法

    方法一: 这种方式最简便,首选这种,但是有时会因为不明原因而不好使,我自己电脑刚开始用这种方式是行得通的,但是后来中途装过很多乱七八糟的软件,估计环境变量改乱了,这时候只能用第二种或者第三种方法.先说 ...

  8. Marlin (思维)

    The city of Fishtopia can be imagined as a grid of 44 rows and an odd number of columns. It has two ...

  9. P4578 [FJOI2018]所罗门王的宝藏

    传送门 考虑一个位置答案传递性,如果某个位置的红宝石转动确定了,那么会引起连锁反应: 如图,绿色的转动确定了,那么那两个蓝色的转动也确定了 自己手玩一下,发现如果有解那么随便找一个开始然后一路玩下去最 ...

  10. hbuilder设置自动px 转换成rem

    hbuilder里面有自动换算的 需要设置一下:工具–>选项–>Hbuilder–>代码助手设置.里面有个px自动转rem设置,按自己的实际情况设置就可以在每次输入px的时候有提示了 ...