How does open() work with and without `with`?

后端 未结 3 1597
逝去的感伤
逝去的感伤 2021-02-13 11:50

I\'d like to write a function similar to open. I\'d like to be able to call it with with, but also without with.

When I use

3条回答
  •  情歌与酒
    2021-02-13 12:42

    You have this:

    @contextmanager
    def versioned(file_path, mode):
        # some setup code
        yield versioned_file
        # some teardown code
    

    Your basic problem of course is that what you yield from the context manager comes out of the with statement via as, but is not the object returned by your function. You want a function that returns something that behaves like the object open() returns. That is to say, a context manager object that yields itself.

    Whether you can do that depends what you can do with the type of versioned_file. If you can't change it then you're basically out of luck. If you can change it then you need to implement the __enter__ and __exit__ functions as specified in PEP 343.

    In your example code, though, it already has it, and your teardown code is the same as what it does itself on context exit already. So don't bother with contextlib at all, just return the result of open().

    For other examples where you do need __enter__ and __exit__, if you like the contextlib style (and who doesn't?) you can bridge the two things. Write a function context that's decorated with @contextmanager and yields self. Then implement:

    def __enter__(self):
        self.context = context() # if context() is a method use a different name!
        return self.context.__enter__()
    def __exit__(self, *args):
        return self.context.__exit__(*args)
    

    It's basically up to you whether you find this better or worse than separating out the setup code into __enter__ and the teardown code into __exit__. I generally find it better.

提交回复
热议问题