Search code examples
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

  • The parser maintains a seen_actions set object while parsing (in the _parse_known_args method). At the end of parsing it checks this set against the required arguments (ones with required=True), and may issue a error. A variation is also used with mutually exclusive groups.

    But this variable is not available outside of that function. So short of some sort of 'hook' that lets you apply your own tests within the parse_args action, your best option is to test defaults. Or you can look at sys.argv[1:].

    The default default is None. That is nice for this purpose because your user cannot give this value. That is, there's no string that converts to None (at least not in any of the normal type methods).

    parser.add_argument('--foo') # default=None
    ...
    if args.foo is None:
        # clearly foo has not been specified.
        args.foo = 'the real default'
    else:
        # foo was specified
        pass