Python argparse: nargs='?' and optional arguments

argparse, python

Solution

No, it will not recognize this. You are in the last example clearly passing in `input.in` to `--output`.

I would recommend that you flip the `default` and the `const` parameters. You want the default to be default.out, so it should be `default='default.out'`. `const` can then be set to something else for the case of having an empty `--output` parameter.

That way you don't have to add the `--output` parameter unless you want to change the default, and you can use an empty `--output` parameter if you want to output to `stdout` for example.

Problem

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?

Original source