pythonargparse

How to find out if argparse argument has been actually specified on command line?


I am using arparse to update a config dict using values specified on the command line. Since i only want to update the values in the config for which a value was explicitly mentioned on the command line.

Therefore i try to identify not-specified arguments by checking for each action if getattr(args, action.dest) == action.default or equality of the type converted arg. Then i update all my values in the dict for which this is false.

But this of course fails, if i explicitly specify an argument on the command line which is the same as my default argument. Is there a possibility to identify these explicitly mentioned arguments withing argparser or do i have to identify them manually in sys.argv?

Thanks!

Edit:

To make my intentions clearer. I have an argument like the following:

parser.add_argument('--test', default='meaningful_default')

and a config like

config = { 'test' : 'nondefault_val'}

Now i want to update the config only with the explicitly specified arguments. Comparing the args attributes with the default values works as long as i don't specify something like prog.py --test meaningful_default to update my config again with a value which just happens to be also the default value


Solution

  • If you prefer to use argparse and to be able to specify default values, there is a simple solution using two parsers.

    I. Define your main parser and parse all your arguments with proper defaults:

    parser = argparse.ArgumentParser()
    parser.add_argument('--test1', default='meaningful_default1')
    parser.add_argument('--test2', default='meaningful_default2')
    ...
    args, unparsed = parser.parse_known_args()
    

    II. Define an aux parser with argument_default=argparse.SUPPRESS to exclude unspecified arguments. Add all the arguments from the main parser but without any defaults:

    aux_parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
    for arg in vars(args): aux_parser.add_argument('--'+arg)
    cli_args, _ = aux_parser.parse_known_args()
    

    This is not an extremely elegant solution, but works well with argparse and all its benefits.