I've written a command line utility that uses getopt for parsing arguments given on the command line. I would also like to have a filename be an optional argument, such as it is in other utilities like grep, cut etc. So, I would like it to have the following usage
tool -d character -f integer [filename]
How can I implement the following?
- if a filename is given, read from the file.
- if a filename is not given, read from STDIN.
To make use of python's
with
statement, one can use the following code:In the simplest terms:
At this point you would use
inf
to read from the file. Depending on whether a filename was given, this would read from the given file or from stdin.When you need to close the file, you can do this:
However, in most cases it will be harmless to close
sys.stdin
if you're done with it.I prefer to use "-" as an indicator that you should read from stdin, it's more explicit:
The fileinput module may do what you want - assuming the non-option arguments are in
args
then:If
args
is empty thenfileinput.input()
will read from stdin; otherwise it reads from each file in turn, in a similar manner to Perl'swhile(<>)
.Something like:
I like the general idiom of using a context manager, but the (too) trivial solution ends up closing
sys.stdin
when you are out of thewith
statement, which I want to avoid.Borrowing from this answer, here is a workaround:
I suppose you could achieve something similar with
os.dup()
but the code I cooked up to do that turned out to be more complex and more magical, whereas the above is somewhat clunky but very straightforward.