当前位置:编程学习 > python >>

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')

 

print

 

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 ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,