Python: Как правилно да създавате и унищожавате ресурси с помощта на модела на дескриптора на contextmanager

Изпълнявам създаването и унищожаването на ресурси по следния начин:

import weakref

class Context(object):
    def __init__(self):
        self.resource = object()  # sample resource creation

    def __del__(self):
        self.resource = None  # destroy resource but keep attribute (compare with 'del')

    def get_resource(self):
        """
        return a proxy of the resource so that only this context 
        instance holds a valid instance and can therefore destroy it 
        when it wants to no matter if another 'reference' is hold 
        elsewhere
        """
        return weakref.proxy(self.resource)

class ContextManager(object):
    def __init__(self):
        self._context = None  # create attribute

    def __enter__(self):
        self._context = Context()
        return self._context  # make the context available in the 'with .. as ..' statement

    def __exit__(self, type, value, traceback):
        self._context = None


if __name__ == "__main__":

    with ContextManager() as c:
        print(c.get_resource())  # do something with resource

    """
    although we have left the scope of the with statement this print
    still executes and a check with gc.get_referrers still shows the 
    references in use
    """
    print(c.resource)

Въпросът ми е свързан с последния ред код:

Защо контекстът и/или ресурсът все още са налични, въпреки че обхватът на оператора with е оставен, което трябва да извика функцията __exit__?


person morph    schedule 12.05.2015    source източник


Отговори (1)


Грешах, когато приех поведение на обхвата, което познавам от C/C++, за да работи и с python. Решението на моя проблем е да върна слаб ref.прокси на контекста:

def __enter__(self):
    self._context = Context()
    return weakref.proxy(self._context)
person morph    schedule 12.05.2015