美文网首页
python--context上下文管理器

python--context上下文管理器

作者: 凉初透的风 | 来源:发表于2019-03-29 17:30 被阅读0次
    上下文管理器

    语法

    with EXPR as VAR:
        BLOCK
    

    概念

    1. 上下文表达式:with open('hello.txt') as f:
    2. 上下文管理器:open('hello.txt')
    3. f 不是上下文管理器,是资源对象
    
    为什么要用上下文管理器?

    1.可以以一种更加优雅的方式,操作(创建/获取/释放)资源,如文件操作、数据库连接;
    2.可以以一种更加优雅的方式,处理异常;

    如何实现上下文管理器

    实现这样一个上下文管理,要先知道上下文管理协议。
    简单点说,就是在一个类里,实现了enterexit的方法,这个类的实例就是一个上下文管理器。

    示例

    class Resource():
        def __enter__(self):
            print('===connect to resource===')
            return self
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('===close resource connection===')
            
        def operate(self):
            print('===in operation===')
            
    with Resource() as res:
        res.operate()
    

    输出

    ===connect to resource===
    ===in operation===
    ===close resource connection===
    

    在编写上下文管理器时,需要将资源的连接或者获取放在enter中,而将资源的关闭写在exit

    使用contextlib

    编写enterexit仍然很繁琐,因此Python的标准库contextlib提供了更简单的写法,上面的代码可以改写如下:

    from contextlib import contextmanager
    
    class Resource():   
        def operate(self):
            print('===in operation===')
    
    @contextmanager
    def create_resource():
        print('Begin')
        q = Resource()
        yield q
        print('End')
    
    with create_resource() as f:
        f.operate()
    

    很多时候,我们希望在某段代码执行前后自动执行特定代码,也可以用@contextmanager实现

    @contextmanager
    def tag(name):
        print("<%s>" % name)
        yield
        print("</%s>" % name)
    
    with tag("h1"):
        print("hello")
        print("world")
    

    输出

    <h1>
    hello
    world
    </h1>
    

    1.with语句首先执行yield之前的语句,因此打印出<h1>;
    2.yield调用会执行with语句内部的所有语句,因此打印出hello和world;
    3.最后执行yield之后的语句,打印出</h1>。

    @closing

    如果一个对象没有实现上下文,我们就不能把它用于with语句。这个时候,可以用closing()来把该对象变为上下文对象。例如,用with语句使用urlopen():

    from contextlib import closing
    from urllib.request import urlopen
    
    with closing(urlopen('https://www.python.org')) as page:
        for line in page:
            print(line)
    

    closing也是一个经过@contextmanager装饰的generator,它的作用就是把任意对象变为上下文对象,并支持with语句,这个generator编写起来其实非常简单:

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

    本文采纳以下文章部分内容:

    https://www.cnblogs.com/wongbingming/p/10519553.html

    https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001478651770626de401ff1c0d94f379774cabd842222ff000

    相关文章

      网友评论

          本文标题:python--context上下文管理器

          本文链接:https://www.haomeiwen.com/subject/ruhrbqtx.html