I combined @Blckknght's answer with Method 3 from Creating a singleton in Python, using metaclass.
from abc import ABCMeta, abstractmethod
from functools import wraps
import time
class Singleton(ABCMeta):
    _instance = None
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance") or cls._instance is None:
            cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instance
class ContextDecorator(object):
    __metaclass__ = Singleton
    def __init__(self, *args, **kwargs):
        self.args = args
        self.__dict__.update(kwargs)
        self._built = False
        self._contextExists = False
    @abstractmethod
    def _build(self):
        pass
    @abstractmethod
    def _destory(self):
        pass
    @classmethod
    def clear_singleton(cls):
        cls._instance = None
    def __enter__(self):
        if not self._built:
            self._build()
            self._built = True
            print 'call _build first time'
        else:
            print 'skip _build'
            self._contextExists = True
        return self
    def __exit__(self, typ, val, traceback):
        if not self._contextExists:
            self._destory()
            self.clear_singleton()
            # self._contextExists=False
            print 'call _destory first time'
        else:
            print 'skip _destory'
            self._contextExists = False
    def __call__(self, f):
        self.function = f
        @wraps(f)
        def wrapper(*args, **kw):
            with self:
                try:
                    return f(*args, **kw)
                except:
                    raise
        return wrapper
class CustomContext(ContextDecorator):
    def __init__(self, *args, **kwargs):
        super(CustomContext, self).__init__(*args, **kwargs)
    def _build(self):
        pass
    def _destory(self):
        pass
print 'context managere test'
with CustomContext():
    for i in range(3):
        with CustomContext():
            time.sleep(0.01)
print '-' * 10
print 'decorator test'
@CustomContext()
@CustomContext()
def test():
    print 'in side test func'
test()
And the output
context managere test
call _build first time
skip _build
skip _destory
skip _build
skip _destory
skip _build
skip _destory
call _destory first time
----------
decorator test
call _build first time
skip _build
in side test func
skip _destory
call _destory first time