I ran across this problem while writing some code for a challenge.
I have some code that I want to write to a particular file if a filename is provided, or standard output if not:
with (open(filename, 'w') if filename else sys.stdout) as file: do_something(file)
with line is a bit long, and doesn't seem readable at a glance. I could put the
open outside the
f = open(filename, 'w') if filename else sys.stdout with f as file: do_something(file)
The file should be closed when the
with is exited. I'm done with
stdout in this case, but I could just have well have wanted to use it for other things later on in the program. But the worst thing about this way of doing it seems to be that making a habit of using
open outside a
with expression could lead to forgetting to close files.
I could go the try/finally route:
try: f = open(filename, 'w') if filename else sys.stdout do_something(f) finally: if f is not sys.stdout: f.close()
But this seems a bit verbose and reminds me too much of Java, which, as a rule of thumb, probably means it's not Pythonic.
I could write a context manager to hide the "check if it's stdout and close it" logic:
from contextlib import contextmanager @contextmanager def file_or_stdout(fname): if fname: f = open(fname, 'w') yield f f.close() else: yield sys.stdout with file_or_stdout(filename) as file: do_something(file)
This seems pretty clear, but it also might be overkill. I'm leaning toward this though, as it leaves the
do_something block plenty of room for clarity, and I could extract the
file_or_stdout function into a utility library so it's not cluttering up the file.