I have a bunch of small Python scripts meant to read from stdin and write to stdout if input and/or output files aren’t given, you know, the usual Unix pipeline idiom. Note that I’m not piping within the program, just reading from stdin, writing to stdout (so packages like the pipe
package on PyPI aren’t useful here). Many years ago, I originally wrote them something like so:
inf = open((args[0] if args else "/dev/stdin"), "r")
outf = open((args[1] if len(args) > 1 else "/dev/stdout"), "w")
...
This works, but note that I wasn’t specifying encodings to the open
calls, nor was I using the with
statement. I may or may not have explicitly remembered to close the files. (Much of this code predates with
by a long ways.)
I’ve been working to bring standard practice to these scripts, and now do something like this:
with ((open(args[0], "r", encoding=options.encoding)
if len(args) >= 1 else sys.stdin) as inf,
(open(args[1], "w", encoding=options.encoding)
if len(args) == 2 else sys.stdout) as outf):
...
This also works, but is a mouthful, and… pylint complains that I have a bunch of duplicate lines across these related scripts. (I should probably open /dev/stdin
and /dev/stdout
with the desired encoding, but that’s a minor thing.) If I was still not using the with
statement, I could open both files in a function and just return the open file handles, something like:
(inf, outf) = open_both(args[0] if len(args) >= 1 else "/dev/stdin",
args[1] if len(args) == 2 else "/dev/stdout",
options.encoding)
...
That’s still a mouthful, but I could probably whittle down the if/else expressions a bit.
My question: How do I push the file open logic into a function in the face of the desire to use with
statements?