How would you rewrite this Python code?

cathodion

Dustin King

Posted on May 26, 2018

How would you rewrite this Python code?

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)
Enter fullscreen mode Exit fullscreen mode

That with line is a bit long, and doesn't seem readable at a glance. I could put the open outside the with:

f = open(filename, 'w') if filename else sys.stdout
with f as file:
    do_something(file)
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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.

Any thoughts?

💖 💪 🙅 🚩
cathodion
Dustin King

Posted on May 26, 2018

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related