On Nov 18, 2019, at 09:47, Paul Moore
But open() isn't designed *just* to be used in a with statement. It can be used independently as well. What about
f = open(filename) header = f.readline() with f: # use f
The open doesn't "create a future need to call __exit__". It *does* require that the returned object gets closed at some stage, but you can do that manually (for example, if "header" in the above is "do not process", maybe you'd close and return early).
And if readline or the comparison raises an exception, you want to leak f? Unless there’s some case where you don’t want to close f at all, I don’t see why you don’t want a context manager. For example, your return early case: with open(filename) as f: header = f.readline() if something(header): return # use f … does exactly what you wanted, and also properly handles exceptions. Which is the whole point of context managers. I suppose if you wanted to close f in some different way in some situations… but there is no different way to close files. And in fact, I think any object that has multiple different ways to call it shouldn’t be a context manager (if there’s not one obvious thing that “exit” means, how do you read it?); you’d want to have methods or functions to create multiple different context managers around that object. But for files, that isn’t an issue. Every call to open does create a future need to call close, and __exit__ obviously means close for files, so every call to open does create a future need to call __exit__ after all. There are cases where that future close may not be lexically bound. Maybe for some cases you close the file at the end of the function, but for other cases you pass the file off to a daemon thread that will close the file when it finishes (or just leak the file and let the OS handle it if it doesn’t finish). That seems like a case for ExitStack rather than for using a file as a context manager.