Python中的 @contextmanger装饰器

Python中的 @contextmanger装饰器

十月 03, 2018

【如何使用contextmanger装饰器实现一个上下文管理器?】

《flask核心机制——Flask中的上下文》 一文中已经介绍过了with语句的使用以及上下文管理器的定义。

此文中介绍了只有一个对象实现了 __enter__ 和 __exit__ 这两个方法,才是实现了上下文协议。

那么,在这个对象没有实现这两个方法的前提下,我们依然想对该对象使用with语句的情况下,可以使用contextmanger装饰器来实现。

一个上线文管理器的示例

# 一个上线文管理器的示例
class MyResource:

    def __enter__(self):
        print('connect to resource')
        return self # 返回MyResource

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('close resource connection')

    @staticmethod
    def query():
        print('query data')

一个普通的类,没有实现上下文协议的对象

# 一个普通的类,没有实现上下文协议的对象
class MyResource:

    @staticmethod
    def query():
        print('query data')

from contextlib import contextmanger

@contextmanger
def make_myresource():
    print('connect to resource')
    yield MyResource() # return会直接返回给函数调用出。yield生成器会让程序处于一个中断的状态
    print('close resource connection')

with make_myresource() as r:
    r.query()

[@contextmanger的作用和意义]

@contextmanger去定义上下文管理器的方法。他为我们提供了一个途径,把原来不是上下文管理器的类变成了一个上下文管理器。比如某一个类是框架或者第三方类库提供给我们的,我们可以在类的外部使用@contextmanger装饰器自己把这个类包装成上下文管理器。