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() ...
随机推荐
- zbar
源码下载链接:http://sourceforge.net/projects/zbar
- vector<vector<int>> 使用简单示例
#include <iostream> #include <vector> using namespace std; int main() { vector<vector ...
- Qt 学习之路 2(39):遍历容器
Qt 学习之路 2(39):遍历容器 豆子 2013年1月16日 Qt 学习之路 2 29条评论 上一节我们大致了解了有关存储容器的相关内容.对于所有的容器,最常用的操作就是遍历.本章我们将详细了解有 ...
- N1 Armbian 安装 OpenMediaVault
前言 接上一篇继续折腾,这次在 N1 上进行一些本地化设置并安装使用 OpenMediaVault 步骤 使用 ssh 连接到 N1,修改系统源 cd /etc/apt cp sources.list ...
- Apache 配置 http 转 https
<IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteCond %{SERVER_PORT} !^443$ Rewr ...
- JavaScript笔记Array.filter(Boolean)
ECMAScirpt5 中 Array 类中的 filter 方法使用目的是移除所有的 ”false“ 类型元素 (false, null, undefined, 0, NaN or an empt ...
- Trailing Loves (or L'oeufs?)
The number "zero" is called "love" (or "l'oeuf" to be precise, literal ...
- Spring 配置 Apache Commons Logging
第一次用spring framework,刚配了个最简单的项目,启动出现如下错误,查了知道原来spring要依赖Apache common logging包.只需要添加到项目library中即可.可从 ...
- vim(二) 代码查看
ctags,cscope 查看代码 生成cscope脚本文件 #!/bin/bash if [ -f "*.cscope" ]; then rm -fr *.cscope fi i ...
- docker 解决容器时间与主机时间不一致的问题
环境: 1.阿里云ecs服务器 2.docker 3.docker镜像 centos7.4.1708 方法一: 查看主机时间: [root@iZbp1625jeg61bc2zzfcotZ docker ...