I have a program in Python 3.8 which takes multiple different commands (e.g. mode
), each of which have a different valid constellation of the same options (i.e., one option might be only valid in two commands, another in all of them, etc.) I therefore want to define each option (say --my-arg
) once, as a argument dictionary (e.g. my_arg
), and then pass it to multiple add_argument
calls as appropriate for each command using **
. But for some reason, the option_strings
is being dropped in the call, and I don't know why.
Minimum reproducible example:
import argparse
parser = argparse.ArgumentParser('Test keyword arguments')
arg_parser = parser.add_subparsers(dest='what_to_run')
parser_mode = arg_parser.add_parser('mode')
my_arg = {'option_strings': ['--my-arg'], 'dest': 'my_arg',
'help': 'My string argument goes here'}
parser_mode.add_argument(**my_arg)
parser.parse_args(['mode', '--my-arg', 'my value'])
This is the latter part of the output:
>>> parser_mode.add_argument(**my_arg)
_StoreAction(option_strings=[], dest='my_arg', nargs=None, const=None, default=None, type=None, choices=None, help='My string argument goes here', metavar=None)
>>> parser.parse_args(['mode', '--my-arg', 'my value'])
usage: Test keyword arguments [-h] {mode} ...
Test keyword arguments: error: unrecognized arguments: --my-arg
Note that option_strings
is []
, when ['--my-arg']
is expected.
If instead I replicate the option as a positional argument and remove it from the dictionary, it works:
import argparse
parser = argparse.ArgumentParser('Test keyword arguments')
arg_parser = parser.add_subparsers(dest='what_to_run')
parser_mode = arg_parser.add_parser('mode')
my_arg = {'dest': 'my_arg', 'help': 'My string argument goes here'}
parser_mode.add_argument('--my-arg', **my_arg)
parser.parse_args(['mode', '--my-arg', 'my value'])
Output:
>>> parser_mode.add_argument('--my-arg', **my_arg)
_StoreAction(option_strings=['--my-arg'], dest='my_arg', nargs=None, const=None, default=None, type=None, choices=None, help='My string argument goes here', metavar=None)
>>> parser.parse_args(['mode', '--my-arg', 'my value'])
Namespace(my_arg='my value', what_to_run='mode')
This is a tolerable fix, I suppose (I guess I could write a function to do this for me...), but I beyond wanting to eliminate duplication, I want to understand what's going on.