zoukankan      html  css  js  c++  java
  • Python之上下文管理

    http://www.cnblogs.com/coser/archive/2013/01/28/2880328.html

    上下文管理协议为代码块提供包含初始化和清理操作的上下文环境。即便代码块发生异常,清理操作也会被执行。

    Context对象

    *__enter__:初始化环境,返回上下文对象

    *__exit__:执行清理操作。返回True时,将阻止异常向外传递

    #!/usr/bin/env python26
    #-*- coding:utf-8 -*-
    
    class MyContext(object):
            def __init__(self,*args):
                    self._data = args
            def __enter__(self):
                    print "__enter__"
                    return self._data #不一定要返回上下文对象自身
    
            def __exit__(self,exc_type,exc_value,traceback):
                    if exc_type:
                            print "Exception:",exc_value
                    print "__exit__"
    
                    return True#阻止异常向外传递
    with MyContext(1,2,3) as data: #将__enter__返回的对象赋给data
            print data
    print '*'*30
    
    with MyContext(1,2,3): #发生异常,显示并拦截
            raise Exception("data error!")

    输出:

    __enter__
    (1, 2, 3)
    __exit__
    ******************************
    __enter__
    Exception: data error!
    __exit__

    上面的模式,需要重写__enter__和__exit__,比较麻烦。contextlib可以解决这个问题。

    contextlib

    标准库contextlib提供一个contextmanager装饰器,用来简化上下文类型开发。

    #!/usr/bin/env python26
    #-*- coding: utf-8 -*-
    
    from contextlib import contextmanager
    
    @contextmanager
    def closing(o):
            print "__enter__"
            yield o
    
            print "__exit__"
            o.close()
    
    with closing(open("readme.txt","r")) as f:
            print f.readline(),

    contextmanger替我们创建Context对象,并利用yield切换执行过程。

    *通过__enter__调用closing函数,将yield结果作为__enter__返回值

    *yield让出closing执行权限,转而执行with代码块

    *执行完毕,__exit__发生消息,通知yield恢复执行closing后续代码

    contextmanger让我们少写很多代码,因为不是自己写__exit__,所以得额外处理异常。

    上下文管理协议的用途很广,比如:

    1、Synchronized:为代码块提供lock/unlock线程同步;

    2、DBContext:为代码块中的逻辑提供共享的数据库连接,并负责关闭连接。

    此处先记着,待等到实际应用的时候再更新相关的理解。

    具体的例子

    1、计算函数的执行时间:

    import time
    
    class Context(object):
    
        def __init__(self):
            self.start = None
            self.end = None
    
        def __enter__(self):
            self.start = time.time()
            print "Start"
            return self
    
        def __exit__(self, exctype, excvalue, traceback):
            print "exit"
            self.end = time.time()
    
            print "End:"
            print 'Cost:%d' % (self.end - self.start)
            return self
    
    def test():
        return Context()
    
    with test():
        print 'int test'
        time.sleep(2)
    

      

    输出结果:

    Start
    int test
    exit
    End:
    Cost:2
    

     

    2、使用装饰器的方式

    #在装饰器内部使用with语法
    def with_decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            with Context():
                return func(*args, **kwargs)
        return wrapper
    
    @with_decorator
    def test_decorator():
    

      

      

     

  • 相关阅读:
    Python---列表相关操作
    PyCharm使用小技巧--git上传代码至远程仓库
    Linux下修改文件权限
    Linux运行jmeter
    Jmeter添加负载机
    git使用
    Linux之12——常用统计命令之uniq
    Linux之11——常用统计命令之sort
    Linux之10——dd命令详解
    Linux之8——性能调优之iostat命令详解
  • 原文地址:https://www.cnblogs.com/gsblog/p/3363297.html
Copyright © 2011-2022 走看看