Python argparse: nargs='?' and optional arguments

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.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.


You can pass "--" to mark the end of any options. For instance:

python readfile.py --output -- input

has the intended effect. However, making the argument to --output required and allowing:

python readfile.py --output - input

is probably cleaner.

链接地址: http://www.djcxy.com/p/28554.html

上一篇: argparse可选的位置参数和子分析器参数

下一篇: Python argparse:nargs ='?' 和可选参数