Let’s say I have a simple program called readfile.py which supports command line arguments by using Python’s argparse.
The program reads from a file specified by the positional argument input. Without specifying additional arguments, this program is not very exciting. It just reads from input and exits. The optional argument --output [OUTPUT_FILE] signifies that the input file should be written to a file. OUTPUT_FILE is also optional. If it is not specified, the input should be written to default.out.
I set up my argument parser like this:
parser = argparse.ArgumentParser(description='Read from a file')
parser.add_argument(
'input',
help='file to read from')
parser.add_argument(
'--output',
nargs='?',
const='default.out',
default=None,
help="""write file to %(metavar)s. If %(metavar)s isn't
specified, write file to %(const)s.""",
metavar='OUTPUT_FILE')
args = parser.parse_args()
return args.file, args.output_file
Note I use default=None so that if --ouput doesn’t appear on the command line, I can detect its absence with None.
Which gives a usage signature like this:
usage: readfile.py [-h] [--output [OUTPUT_FILE]] input
This handles arguments as expected if I run
python readfile.py input.in --output somefile.out
or
python readfile.py --output somefile.out input
It sets output to default.out if I run
python readfile.py input.in --output
but if I run
python readfile.py --output input.in
it complains about there being too few arguments. I thought argparse would be ‘smart’ enough to interpret this pattern, setting input to input.in and output to default.out. The generated usage even suggests this.
Am I missing something?
No, it will not recognize this. You are in the last example clearly passing in
input.into--output.I would recommend that you flip the
defaultand theconstparameters. You want the default to be default.out, so it should bedefault='default.out'.constcan then be set to something else for the case of having an empty--outputparameter.That way you don’t have to add the
--outputparameter unless you want to change the default, and you can use an empty--outputparameter if you want to output tostdoutfor example.