This sounds like a variation on the - how do I accept arbitrary 'key=value' pairs? It's been asked in various ways over the years, with various answers.
In a recent one:
Parsing "python foo.py -DVAR1=9 -DVAR2=Off" with argparse
my solution was to split -DVAR1=9
into ('VAR1',9)
and append that to the D
attribute. That uses a custom type
.
Using variable arg names with argparse - this processes the sys.argv
before passing it to the parser.
python argparse store --foo=bar as args.key='foo', args.value='bar'
suggests a custom Action
class.
I think we've also suggested a custom Namespace
class.
The builtin mechanisms for grouping values are nargs
and append
action. Together you can get attributes which are lists of lists.
JSON strings can also be used to input complex data structures.
class MyAction(argparse._StoreAction):
def __call__(self, parser, namespace, values, option_string=None):
print('storing', option_string)
arg = getattr(namespace, self.dest)
if arg is None:
arg = {}
arg[option_string] = values
setattr(namespace, self.dest, arg)
In [135]: p=argparse.ArgumentParser()
In [136]: p.add_argument('--p1',action=MyAction,dest='p');
In [137]: p.add_argument('--p2',action=MyAction,dest='p');
In [138]: p.parse_args('--p1 one --p2 two'.split())
storing --p1
storing --p2
Out[138]: Namespace(p={'--p2': 'two', '--p1': 'one'})
In [139]: _.p
Out[139]: {'--p1': 'one', '--p2': 'two'}
Obviously this could be refined in various ways - trimming the keys to 'p1' or even '1', saving to a list, or nested Namespace or other custom structure, etc.
This approach still requires that you define an add_argument
for each '--pn` variation.
An alternative is keep argparse
simple, producing a namespace like:
In [141]: argparse.Namespace(p1='one', p2='two', input1=1, input2=3)
Out[141]: Namespace(input1=1, input2=3, p1='one', p2='two')
and then do your own grouping afterwards.
In [142]: args=argparse.Namespace(p1='one', p2='two', input1=1, input2=3)
In [143]: {key:getattr(args,key) for key in ['p1','p2']}
Out[143]: {'p1': 'one', 'p2': 'two'}