python模块介绍 contextlib—上下文管理器工具
contextlib—上下文管理器工具
2012-07-27 磁针石
#承接软件自动化实施与培训等gtalk: ouyangchongwu#gmail.com qq 37391319博客:testing.blog.chinaunix.net
#版权所有,转载刊登请来函联系
#自动化测试和python群组: http://groups.google.com/group/automation_testing_python
#参考资料:《ThePython Standard Library by Example》
# 实验环境:Python2.7.3 CentOS release 6.2 (Final) 32bits
3.4 contextlib—上下文管理器工具
作用:创建和处理上下文管理器的工具。
Python版本:2.5及以后版本
contextlib模块包含一些工具,用于处理上下文管理器和with语句。上下文管理器和with语句,可以减少try:finally块的个数和所需的缩进层次。
注意:上下文管理器要与with语句关联。由于官方认为with是Python 2.6的一部分,因此在Python2.5中使用contextlib之前要从__future__将其导入。比如from__future__ import with_statement。
3.4.1 上下文管理器API
上下文管理器(context manager)要负责一个代码块中的资源,可能在进入代码块时创建资源,然后在退出代码块时清理这个资源。例如,文件支持上下文管理器API,可以很容易地确保完成文件读写后关闭文件。
with open(’/tmp/pymotw.txt’,’wt’) as f:
f.write(’contents go here’)
# file isautomatically closed
上下文管理器由with语句启用,这个API包括两个方法。当执行流进入with中的代码块时会运行__enter__()方法。它会返回一个对象,在这个上下文中使用。当执行流离开with块时,则调用这个上下文管理器的__exit__()方法来清理所使用的资源。
#!/usr/bin/envpython
# encoding:utf-8
#
# Copyright(c) 2010 Doug Hellmann. All rightsreserved.
#
"""Implementingthe context manager API by hand.
"""
#end_pymotw_header
classContext(object):
def __init__(self):
print '__init__()'
def __enter__(self):
print '__enter__()'
return self
def __exit__(self, exc_type, exc_val,exc_tb):
print '__exit__()'
withContext():
print 'Doing work in the context'
结合上下文管理器与with语句是try:finally块的一种更紧凑的写法,因为上下文管理器的__exit__()方法总会调用,即使在产生异常的情况下也是如此。执行结果如下:
# python contextlib_api.py
__init__()
__enter__()
Doing work inthe context
__exit__()
如果在with语句的as子句中指定了名称,__enter__()方法可以返回与这个名称相关联的任何对象。在这个例子中,Context会返回使用了上下文的对象。
#!/usr/bin/env python
# encoding:utf-8
#
# Copyright(c) 2010 Doug Hellmann. All rightsreserved.
#
"""Implementingthe context manager API by hand.
"""
#end_pymotw_header
classWithinContext(object):
def __init__(self, context):
print 'WithinContext.__init__(%s)' %context
def do_something(self):
print 'WithinContext.do_something()'
def __del__(self):
print 'WithinContext.__del__'
classContext(object):
def __init__(self):
print 'Context.__init__()'
def __enter__(self):
print 'Context.__enter__()'
return WithinContext(self)
def __exit__(self, exc_type, exc_val,exc_tb):
print 'Context.__exit__()'
withContext() as c:
c.do_something()
执行结果:
pythoncontextlib_api_other_object.py
Context.__init__()
Context.__enter__()
WithinContext.__init__(<__main__.Contextobject at 0xb77684cc>)
WithinContext.do_something()
Context.__exit__()
WithinContext.__del__
__exit__()方法接收一些参数,其中包含with块中产生的异常的详细信息
#!/usr/bin/env python
# encoding:utf-8
#
# Copyright(c) 2010 Doug Hellmann. All rightsreserved.
#
"""Implementingthe context manager API by hand.
"""
#end_pymotw_header
classContext(object):
def __init__(self, handle_error):
print '__init__(%s)' % handle_error
self.handle_error = handle_error
def __enter__(self):
print '__enter__()'
return self
def __exit__(self, exc_type, exc_val,exc_tb):
print '__exit__()'
print ' exc_type =', exc_type
print ' exc_val =', exc_val
print ' exc_tb =', exc_tb
return self.handle_error
withContext(True):
raise RuntimeError('error message handled')
withContext(False):
raiseRuntimeError('error message propagated')
如果上下文管理器可以处理这个异常,__exit__() 应当返回一个true值来指示不需要传播这个异常。如果返回false,就会导致__exit__()返回后重新抛出这个异常。执行结果如下:
# pythoncontextlib_api_error.py
__init__(True)
__enter__()
__exit__()
exc_type = <type'exceptions.RuntimeError'>
exc_val = error message handled
exc_tb = <traceback object at 0xb7691504>
__init__(False)
__enter__()
__exit__()
exc_type = <type'exceptions.RuntimeError'>
exc_val = error message propagated
exc_tb = <traceback object at 0xb769157c>
Traceback(most recent call last):
File "contextlib_api_error.py",line 30, in <module>
raise RuntimeError('error messagepropagated')
RuntimeError:error message propagated
3.4.2从生成器到上下文管理器
采用传统方式创建上下文管理器,即编写一个包含__enter__()和__exit__()方法的类,这并不难。不过有些时候,对于很少的上下文来说, 完全编写所有代码会是额外的负担。在这些情况下,可以使用contextmanager()修饰符将一个生成器函数转换为上下文管理器。
#!/usr/bin/envpython
# encoding:utf-8
#
# Copyright(c) 2008 Doug Hellmann All rights reserved.
#
"""
$Id$
"""
#end_pymotw_header
importcontextlib
@contextlib.contextmanager
defmake_context():
print ' entering'
try:
yield {}
except RuntimeError, err:
print ' ERROR:', err
finally:
&
补充:Web开发 , Python ,