Как использовать Python закрывающий контекстный менеджер - PullRequest
7 голосов
/ 09 ноября 2011

Функция стандартной библиотеки open работает как функция:

f = open('file.txt')
print(type(f))
<type 'file'>

или как менеджер контекста:

with open('file.txt') as f:
    print(type(f))
<type 'file'>

Я пытаюсь имитировать это поведение, используя contextlib.closing, где File - мой класс ввода-вывода для файла:

def myopen(filename):
    f = File(filename)
    f.open()
    return closing(f)

работает как менеджер контекста, как и ожидалось:

with myopen('file.txt') as f:
    print(type(f))
<class '__main__.File'>

но, конечно, если я позвоню напрямую, я получу обратно объект closing вместо моего объекта:

f = myopen(filename)
print(type(f))
<class 'contextlib.closing'>

Итак, как мне реализовать myopen, чтобы он работал как менеджер контекста и возвращает мой объект File при прямом вызове?

Полный рабочий пример на github: https://gist.github.com/1352573

1 Ответ

13 голосов
/ 09 ноября 2011

Возможно, проще всего реализовать методы __enter__ и __exit__ самостоятельно. Примерно так должно это сделать:

class File(object):
   # ... all the methods you already have ...

   # context management
   def __enter__(self):
       return self
   def __exit__(self, *exc_info):
       self.close()

Кстати, было бы более идиоматично выполнять работу вашего open метода в вашем __init__ методе.

...