Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define the order of argparse argument in python

I am trying to use argparse with subparser to switch between 3 fonctionnalities whereas one positional argument should be common to all subparser. Moreover, and it is the key point, i want to put the positional argument as the last argument provided as this one is an output file path. It makes no sense to me to put it at the beginning (as first argument)

import sys,argparse,os

files = argparse.ArgumentParser(add_help=False)
files.add_argument('outfile',  help='output mesh file name')

parser = argparse.ArgumentParser(description="A data interpolation program.",prog='data_interpolate.py',    parents=[files])

subparsers = parser.add_subparsers(help='Mode command.')
command_parser = subparsers.add_parser('cmd',help='Pass all argument in command line.',parents=[files])
command_parser.add_argument('-min', dest='MINFILE',help='Input file with min values', required=True)
command_parser.add_argument('-max', dest='MAXFILE',help='Input file with min values', required=True)
command_parser.add_argument('u', help='Interpolation parameter. Float between 0 and 1. Out of bound values are limited to 0 or 1.')

subparsers.add_parser('py',help='Pass all argument in python file.',parents=[files])
subparsers.add_parser('json',help='Pass all argument in json file.',parents=[files])

Which gives:

data_interpolation.py -h 

usage: data_interpolation.py [-h] outfile {cmd,py,json}

But, to my opinion, the outfile should be given at the end following:

data_interpolation.py [-h] {cmd,py,json} outfile

This has even more sense when using the cmd command as I need to pass other parameter values. For intance:

data_interpolation.py cmd -min minfile.txt -max maxfile.txt 0.6 outfile.txt

How can I set up argparse to have such behaviour?

like image 334
user2550340 Avatar asked Feb 14 '26 07:02

user2550340


1 Answers

(note - this is an old question).

The order of positionals is determined by the order in which they are defined. That includes the subparsers argument (which is a positional with choices and a special action).

Defining outfile as an argument to both the main parser and the subparsers is redundant.

Positionals defined via parents will be placed first. So if 'outfile' must be last, it has to be defined separately for each subparser.

It could also be specified last as postional for the main parser (after the subparser definitions).

In [2]: p=argparse.ArgumentParser()    
In [5]: sp=p.add_subparsers(dest='cmd')
In [6]: spp=sp.add_parser('cmd1')
In [7]: spp.add_argument('test')
In [8]: p.add_argument('out')
In [9]: p.print_help()
usage: ipython [-h] {cmd1} ... out
...

In [11]: spp.print_help()
usage: ipython cmd1 [-h] test
...

In [15]: p.parse_args('cmd1 test out'.split())
Out[15]: Namespace(cmd='cmd1', out='out', test='test')

cmd1 is interpreted as a subparser choice. test is interpreted by the subparser as a positional. out is left over, and returned to the main parser to use as it sees fit. This parsing could be messed up if the subparser does not return any extras. So I'd be wary of specifying a final positional like this.

like image 62
hpaulj Avatar answered Feb 16 '26 21:02

hpaulj