2015-05-12 3 views
0

Я осуществить создание и уничтожение ресурсов следующим образом: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) 

Моим вопрос относится к последней строке коды:

Почему контекст и/или ресурс по-прежнему доступны, хотя область действия с инструкцией была оставлена, что должно было вызвать функцию __exit__?

ответ

0

Я ошибался, когда предполагал, что поведение области видимости я знаю из C/C++ для работы с python. Решение моей проблемы состоит в том, чтобы вернуть слабую ссылку на контекст:

def __enter__(self): 
    self._context = Context() 
    return weakref.proxy(self._context)