Как написать функцию, которую можно вызывать и использовать в качестве менеджера контекста? - PullRequest
0 голосов
/ 13 июня 2018

Встроенный open() может использоваться как функция или как менеджер контекста.

f = open(filename)
f.read()

with open(filename) as f:
    f.read()

Я хотел бы написать свою собственную функцию, которая также может использоваться обоими способами.Для простоты примера, скажем, я хочу реализовать функцию myopen().

Что не работает:

Простая функция с контекстным оформлением:

@contextlib.contextmanager
def myopen(filename):
    try:
       f = open(filename)
       yield f
    finally:
       f.close()

>>> myopen(somefile)
<contextlib.GeneratorContextManager at 0x2b6bf7727610>

он возвращает GeneratorContextManager вместо объекта файла.

Класс контекста:

class myopen(object):
    def __init__(self, filename):
        self.filename = filename
        self.file = None

    def __enter__(self):
        self.file = open(filename)
        return self.file

    def __exit__(self):
        self.file.close()

    def __call__(filename):
        return open(filename)

>>> myopen(somefile)
__main__.myopen

Вызов класса, очевидно, создает экземпляр, как и должно быть.Мне пришлось бы создать экземпляр и вызвать его (f = myopen(somefile)()).

...