Reputation: 4820
Consider the following usage:
usage: do.py [-h] [-s | -m] filename
This is not the complete usage. But I effectively want is filename
to be an actual value of file and not:
--filename FILENAME
But also, filename
should be optional so I can read from the standard input. Think about the cat
program on UNIX.
You simply say:
cat filename
OR
cat
EDIT: Right now, if I execute the program do.py
without any command line options, I will get an error: too few arguments
. Instead I would still want it to execute even if I don't give it a valid filename
. How do I do that?
Upvotes: 5
Views: 3137
Reputation: 213298
Update 2: From the ArgParse documentation,
One of the more common uses of nargs='?' is to allow optional input and output files:
>>> parser = argparse.ArgumentParser() >>> parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), ... default=sys.stdin) >>> parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'), ... default=sys.stdout) >>> parser.parse_args(['input.txt', 'output.txt']) Namespace(infile=<open file 'input.txt', mode 'r' at 0x...>, outfile=<open file 'output.txt', mode 'w' at 0x...>) >>> parser.parse_args([]) Namespace(infile=<open file '<stdin>', mode 'r' at 0x...>, outfile=<open file '<stdout>', mode 'w' at 0x...>)
Original answer:
This is straightforward: just add a positional argument with a default value and a nargs='*'
. The default value will be used if there are zero arguments, otherwise the arguments on the command line will be used:
>>> p = argparse.ArgumentParser()
>>> p.add_argument('filename', nargs='*', default=['-'])
>>> p.parse_args([])
Namespace(filename=['-'])
>>> p.parse_args(['abc'])
Namespace(filename=['abc'])
Typically, -
is used to refer to standard input / standard output.
Then you do something like this:
def get_inputs(ns):
"""Iterate over input files."""
for path in ns.filename:
if path == '-':
yield sys.stdin
else:
yield open(path, 'r')
Update: I assumed you wanted multiple filenames, since cat
takes multiple filenames. You can use nargs='?'
if you want either zero or one filename.
Upvotes: 8