Reputation: 35
I have this code
parser = argparse.ArgumentParser()
parser.add_argument('--input')
parser.add_argument('--min')
parser.add_argument('--max')
args = parser.parse_args()
How can I know the order of arguments ? For example, if I type:
python somefile.py --min min --input file.csv
How can I know position of --min
is before --input
and user didn't type --max
?
Upvotes: 2
Views: 1175
Reputation: 231355
By design argparse
is supposed to handle the optionals
in any order. They are parsed in the order that they are provided in the command line, but it does not keep any record of that order. positionals
without a keyword are handled in the order that they are defined by the add_argument
definitions.
All attributes are added to the args
Namespace with their defaults at the start of parsing. And it does this in the add_argument
order. In newer Pythons this order is preserved in the args.__dict__
(which vars(args)
also shows).
But in print(args)
, the attributes are displayed in sorted order. usage
also preserves the definition order for optionals
.
So for a sample parser:
In [11]: p.print_usage()
usage: ipython3 [-h] [--foo FOO] [--test TEST] [--aaa AAA] bar
In [12]: args=p.parse_args(['xxx'])
In [13]: args
Out[13]: Namespace(aaa=None, bar='xxx', foo=None, test=None) # sorted
In [14]: vars(args)
Out[14]: {'foo': None, 'bar': 'xxx', 'test': None, 'aaa': None} # definition
In [15]: [a.dest for a in p._actions]
Out[15]: ['help', 'foo', 'bar', 'test', 'aaa'] # definition order
So recording the order of occurrence of the arguments in the command line is, with just argparse
, awkward. In a sense it goes against the spirit of optionals
.
Alternatives:
work directly with the sys.argv
customize the action
class
customize the Namespace
class
One other trick comes to mind:
If the default
is argparse.SUPPRESS
, the default is not added to args
. Then I think the var(args)
order will be the order in which values are parsed and added.
In [16]: for a in p._actions: a.default=argparse.SUPPRESS
In [24]: args=p.parse_args(['--test', 'ttt','xxx','--foo=3'])
In [25]: args
Out[25]: Namespace(bar='xxx', foo='3', test='ttt')
In [26]: vars(args)
Out[26]: {'test': 'ttt', 'bar': 'xxx', 'foo': '3'}
Users may repeat optionals
, with repeats over writing previous values.
Upvotes: 1
Reputation: 6324
I think it might be tricky to obtain that information from parser itself, but it can be easily obtained from sys.argv:
def get_arg_index(args: list, name: str):
return next((i for i, v in enumerate(args) if v.startswith(name)), None)
print(get_arg_index(sys.argv, "--min"))
print(get_arg_index(sys.argv, "--max"))
Upvotes: 3