contextlib 模块

contextlib.contextmanager(func)

使用contextmanager将一个生成器转化成上下文管理器,而不需要再去实现上下文管理协议。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import contextlib

@contextlib.contextmanager
def createContextManager(name):
print('__enter__ %s' % name)
yield name
print('__exit__ %s' % name)

with createContextManager('foo') as value:
print('----',value)

# __enter__ foo
# ---- foo
# __exit__ foo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from contextlib import contextmanager

class Query(object):
def __init__(self, name):
self.name = name

def query(self):
print('Query info about %s...' % self.name)

@contextmanager
def create_query(name):
print('Begin')
q = Query(name)
yield q
print('End')

with create_query('Bob') as q:
q.query()

# Begin
# Query info about Bob...
# End

contextlib.closing

可以直接用with语句,还有一些对象并不支持该协议,但使用的时候又要确保正常退出,这时就可以使用closing创建上下文管理器。

1
2
3
4
5
6
7
8
9
10
11
12
13
from contextlib import contextmanager
import urllib

@contextmanager
def closing(thing):
try:
yield thing
finally:
thing.close()

with closing(urllib.urlopen('http://www.python.org')) as page:
for line in page:
print line

from __future__ import absolute_import的作用:

比如说,你的包结构是这样的:

1
2
3
4
pkg/ 
pkg/init.py
pkg/main.py
pkg/string.py

如果你在main.py中写import string,那么在Python 2.4或之前, Python会先查找当前目录下有没有string.py, 若找到了,则引入该模块,然后你在main.py中可以直接用string了。如果你是真的想用同目录下的string.py那就好,但是如果你是想用系统自带的标准string.py呢?那其实没有什么好的简洁的方式可以忽略掉同目录的string.py而引入系统自带的标准string.py。这时候你就需要``from future import absolute_import`了。这样,你就可以用import string来引入系统的标准string.py, 而用from pkg import string来引入当前目录下的string.py了