Python contextlib.contextmanager
看着代码又发现了一个奇怪的东西:
@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的更多相关文章
- python 上下文管理器contextlib.ContextManager
1 模块简介 在数年前,Python 2.5 加入了一个非常特殊的关键字,就是with.with语句允许开发者创建上下文管理器.什么是上下文管理器?上下文管理器就是允许你可以自动地开始和结束一些事情. ...
- Python.with.context-manager
Context Manager 1. Context Manager简介 "Context managers are a way of allocating and releasing so ...
- python contextlib 上下文管理器
1.with操作符 在python中读写文件,可能需要这样的代码 try-finally读写文件 file_text = None try: file_text = open('./text', 'r ...
- 源码剖析@contextlib.contextmanager
示例 @contextlib.contextmanager def result(a): print('before') yield print('after') 外层装饰源码 包装func函数,真实 ...
- Python with/as和contextlib上下文管理使用说明
with/as 使用open打开过文件的对with/as都已经非常熟悉,其实with/as是对try/finally的一种替代方案. 当某个对象支持一种称为"环境管理协议"的协议时 ...
- Python——with语句、context manager类型和contextlib库
目录 一.with语句 二.上下文管理器 三.contextlib模块 基本概念 上下文管理协议(Context Management Protocol) 包含方法 __enter__() 和 __e ...
- Python——常用模块(time/datetime, random, os, shutil, json/pickcle, collections, hashlib/hmac, contextlib)
1.time/datetime 这两个模块是与时间相关的模块,Python中通常用三种方式表示时间: #时间戳(timestamp):表示的是从1970年1月1日00:00:00开始按秒计算的偏移量. ...
- Python 上下文管理器模块--contextlib
在 Python 处理文件的时候我们使用 with 关键词来进行文件的资源关闭,但是并不是只有文件操作才能使用 with 语句.今天就让我们一起学习 Python 中的上下文管理 contextlib ...
- python中关于with以及contextlib的使用
一般在coding时,经常使用with来打开文件进行文件处理,然后无需执行close方法进行文件关闭. with open('test.py','r' as f: print(f.readline() ...
随机推荐
- P2407 [SDOI2009]地图复原
$ \color{#0066ff}{ 题目描述 }$ 很久以前,有一个传说中的"EWF"部族,他们世代生活在一个N×M的矩形大地上.虽然,生活的地区有高山.有沼泽,但通过勤劳勇敢, ...
- Takari Extensions for Apache Maven (TEAM)
http://takari.io/book/index.html TEAM stands for the Takari Extensions for Apache Maven. TEAM is a c ...
- Spring学习笔记(六)—— SSH整合
一.整合原理 二.整合步骤 2.1 导包 [hibernate] hibernate/lib/required hibernate/lib/jpa 数据库驱动 [struts2] struts-bla ...
- struts2学习笔记(六)—— 拦截器
一.拦截器概述 拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前进行拦截,然后在之前或之后加入某些操作.拦截器是AOP的一种实现策略. 在We ...
- Android 系统特有的类介绍及使用
1.Content类 在应用程序中Context的具体实现子类就是:Activity,Service,Application.可以把它理解成存储东西的仓库. 常用的上下文一般是类名.class或类名. ...
- POJ1475 Pushing Boxes 华丽丽的双重BFS
woc累死了写了两个半小时...就是BFS?我太菜了... 刚开始以为让人预先跑一遍BFS,然后一会儿取两节加起来就好了,结果发现求出来的最短路(就是这个意思)会因箱子的移动而变化....我死了QWQ ...
- C# B站的弹幕提取
要知道B站的弹幕位置 如果只考虑视频,B站的链接格式为:https://www.bilibili.com/video/av34042815.把av后面的数字看做是唯一标记即可. 既然能够把弹幕加载出来 ...
- 修改chrome背景色
参考:http://blog.csdn.net/jvortex/article/details/73895288 1.新建一个文件夹,比如customcss,包含custom.css和manifest ...
- Oracle sql 中的 ALL,ANY,SOME
[转自] http://www.itpub.net/thread-1355835-1-1.html any和some是等价的,其与all的前面都只能是比较符号,即=, !=, >, <, ...
- js简介 基本操作 以及循环语句 内置对象 函数044
js 全称 javascript 从交互的角度 描述行为 一 .js注释方法: //单行注释 声明变量 var 二 .声明多个变量 : var a = '2' ,b = 4, c = tru ...