T. Zack Crawford
T. Zack Crawford

Reputation: 8846

Customizing optional arguments to include their own positional argument(s)

I would like to have a script which takes command-line arguments including flag options which take positional arguments themselves. I might expect the command line input to look something like

$ ./script.py [-o <file1> <file2> ...] inputfile

The official argparse documentation most similarly talks about

parser.add_argument("-v", "--verbosity", type=int, help="increase output verbosity")
args = parser.parse_args()

where the user inputs a single positional sub-argument (perhaps out of a set of choices) following the -v flag. This positional sub-argument is then stored in args.verbosity.

Thus it appears the flag's argument needs to be included in the same add_argument() line. Can you declare any special name for this sub-argument's variable (say, args.outputfile1)? Can the flag take more than one sub-argument? Can you adjust how the sub-variable looks in the help menu? By default it is something like-o OUTPUT, --output OUTPUT Save output data to a file OUTPUT. Can we change it to read -o <SomethingElse>?

Is there any more documentation which discusses this aspect?

Upvotes: 0

Views: 99

Answers (2)

hpaulj
hpaulj

Reputation: 231395

With a definition like:

parser.add_argument('-o','--output', dest='output_file_name', nargs='+')

you can give a commandline like:

$ ./script.py -o file1 file2

and get args.output_file_name equal to ['file1','file2']. The '+' means one or more arguments (other nargs values are documented).

But

$ ./script.py -o file1 file2 an_input_file

where 'an_input_file' goes to a positional argument is harder to achieve. '*' is greedy, taking everything, leaving nothing for the positional. It's better to define another optional

parser.add_argument('-i','--input')

$ ./script.py -o file1 file2 -i an_input_file

If the '-o' is defined as an 'append' Action, you can use:

$ ./script.py -o file1 -o file2 -i an_input_file

In general you get the best control by using optionals. Positionals, because they 'parse' by position, not value, are harder to use in fancy combinations.

The metavar parameter lets you change the help display.

Upvotes: 1

Maus
Maus

Reputation: 1843

Your proposed interface is pretty unusual. It's more common to have people specify the same option multiple times, because tt's hard to distinguish ./script.py [-o file1 file2 ...] input file from ./script.py [-o file1] file2 inputfile. That might not be an issue yet, but as you add options or god-forbid arguments, your unusual design will become an issue.

I would recommend doing one of the following solutions:

1. Repeat the option flag

./script.py -o file1 -o file2 inputfile

2. Make your option a boolean flag

Change your API so -o indicates that all arguments except the last one are output files: ./script.py -o output1 output2 ... inputfileislast

Upvotes: 1

Related Questions