45fan.com - 路饭网

搜索: 您的位置主页 > 网络频道 > 阅读资讯:怎么样使用Python with?

怎么样使用Python with?

2016-09-02 18:43:45 来源:www.45fan.com 【

怎么样使用Python with?

一 with介绍
with从Python 2.5就有,需要from __future__ import with_statement,但python2.6开始,成为默认关键字。在What's new in python2.6/3.0中,明确提到:
The ‘with‘ statement is a control-flow structure whose basicstructure is:
with expression [as variable]:
with-block
也就是说with是一个控制流语句,跟if/for/while/try之类的是一类的,with可以用来简化try finally代码,看起来可以比try finally更清晰。
这里新引入了一个"上下文管理协议"context management protocol“,实现方法是为一个类定义__enter__和__exit__两个函数。with expresion as variable的执行过程是,首先执行__enter__函数,它的返回值会赋给as后面的variable,想让它返回什么就返回什么,只要你知道怎么处理就可以了,如果不写as variable,返回值会被忽略。然后,开始执行with-block中的语句,不论成功失败(比如发生异常、错误,设置sys.exit()),在with-block执行完成后,会执行__exit__函数。

这样的过程其实等价于:
try:
执行 __enter__的内容
执行 with_block.
finally:
执行 __exit__内容
只不过,现在把一部分代码封装成了__enter__函数,清理代码封装成__exit__函数。

二 代码实现
class echo :
def output(self) :
print 'hello world'
def __enter__(self):
print 'enter'
return self
def __exit__(self, exception_type, exception_value, exception_traceback):
print 'exit'
if exception_type == ValueError :
return True
else:
return False
 
with echo() as e:
e.output()
print 'do something inside'
print '-----------'
with echo() as e:
raise ValueError('value error')
print '-----------'
with echo() as e:
raise Exception('can not detect')
 
 
运行结果:
enter
hello world
do something inside
exit
-----------
enter
exit
-----------
enter
exit
Traceback (most recent call last):
File "exception.py", line 102, in <module>
raise Exception('can not detect')

Exception: can not detect
 
注意:
1,e不是test()的值,test()返回的是"context manager object",是给with用的。e获得的是__enter__函数的返回值,这是with拿到echo()的对象执行之后的结果.

2,__exit__函数的返回值用来指示with-block部分发生的异常是否要re-raise,如果返回False,则会re-raise with-block的异常,如果返回True,则就像什么都没发生。
 
三 使用环境
1.这样要打开一个文件,处理它的内容,并且保证关闭它,你就可以简单地这样做:
with open("x.txt") as f:
data = f.read()
do something with data
 
2.Flask中初始化数据库的代码:
def init_db():
with app.app_context():
db = get_db()
with app.open_resource('shema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
3.contextlib是为了加强with语句,提供上下文机制的模块,它是通过Generator实现的。通过定义类以及写__enter__和__exit__来进行上下文管理虽然不难,但是很繁琐。contextlib中的contextmanager作为装饰器来提供一种针对函数级别的上下文管理机制。常用框架如下:
 
from contextlib import contextmanager
 
@contextmanager
def make_context() :
print 'enter'
try :
yield {}
except RuntimeError, err :
print 'error' , err
finally :
print 'exit'
 
 
with make_context() as value :
print value

contextlib还有连个重要的东西,一个是nested,一个是closing,前者用于创建嵌套的上下文,后则用于帮你执行定义好的close函数。但是nested已经过时了,因为with已经可以通过多个上下文的直接嵌套了。下面是一个例子:

from contextlib import contextmanager
from contextlib import nested
from contextlib import closing
@contextmanager
def make_context(name) :
print 'enter', name
yield name
print 'exit', name
 
with nested(make_context('A'), make_context('B')) as (a, b) :
print a
print b
 
with make_context('A') as a, make_context('B') as b :
print a
print b
 
class Door(object) :
def open(self) :
print 'Door is opened'
def close(self) :
print 'Door is closed'
 
with closing(Door()) as door :
door.open()
 
运行结果:
怎么样使用Python with?
 
closing函数的使用:
 
from contextlib import closing
import urllib
 
with closing(urllib.urlopen('http://www.python.org')) as page:
for line in page:
print line
 
四 小结
python有很多强大的特性,由于我们平常总习惯于之前C++或java的一些编程习惯,时常忽略这些好的机制。因此,要学会使用这些python特性,让我们写的python程序更像是python。
 
 

本文地址:http://www.45fan.com/a/question/71400.html
Tags: python 介绍 with
编辑:路饭网
关于我们 | 联系我们 | 友情链接 | 网站地图 | Sitemap | App | 返回顶部