Can I check if the value was provided by default or by user?

Is there a way, when used, to argparse

determine if a field has a value because the user specified it or because it was not specified and got a default value? Note. I would also like to consider the case where the user explicitly specifies a default.

I would like to use argparse

to handle command line arguments, and I would like to use formatter_class=argparse.ArgumentDefaultsHelpFormatter

to display default values ​​for fields that are not specified. Also, I would like to read the values ​​from the config file.

If the user specifies a value on the command line, I would like to make sure that I use that value (even if that value is the default but explicitly specified). If the user hasn't provided a value, but one is found in the config file, I would like to use it. If the user has not specified it on the command line and there is no value in the config file, I would like to use the default that was specified in the statement above.

So, I can customize the parsing like

parser = parser = argparse.ArgumentParser( description="""Tool with many ways to get values""", formatter_class=argparse.ArgumentDefaultsHelpFormatter )
parser.add_argument( '-p', '--path', help="The path to a file to read", default="data.csv" )
parser.add_argument( '-c', '--conf', help="The config file to use", default="config.txt" )

      

and there are probably many other parameters.

Now I would like to also read the config file which can include the value

data_path = data2.csv

      

So, if the user specifies -p

on the command line, I would like to read this file; if they don't, and I am using this config file, I would like to read data2.csv

; and if I use a config file that doesn't define data_path

, and they don't specify -p

, I would like to use the default data.csv

.

The main tricky case for me would be if the user specifies -p data.csv

then it will have a default but should take precedence over the config file.

Does any argparse

other similar tool have the ability to determine if a parameter was set when it fell to its default value or was explicitly set by the user?

+3


source to share


1 answer


Don't include a default if it just complicates things:

parser.add_argument('-p', '--path', 
                    help="The path to a file to read")

      

And then in your code:

if args.path:
    # user specify a value for path
    # using -p
    pass
elif cfg.path:
    # user provided a path in the configuration value
    args.path = cfg.path
else:
    # no value was specified, use some sort of default value
    args.path = DEFAULT_PATH

      

Or, more compactly:



args.path = next(val for val in 
                 [args.path, cfg.path, DEFAULT_PATH]
                 if val is not None)

      

This assumes what cfg.path

will happen None

if no path is specified in the config file. Therefore, if cfg

in fact it is a dictionary, it cfg.get('path')

will do the right thing.

And just for kicks, here's a terrible idea that can tell the difference between using the default and explicitly specifying a value that is the same as the default:

import argparse

class Default(object):
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return str(self.value)

DEFAULT_PATH = Default('/some/path')

def parse_args():
    p = argparse.ArgumentParser()
    p.add_argument('--path', '-p',
                   default=DEFAULT_PATH)
    return p.parse_args()

def main():
    args = parse_args()

    if args.path is DEFAULT_PATH:
        print 'USING DEFAULT'
    else:
        print 'USING EXPLICIT'

    print args.path

if __name__ == '__main__':
    main()

      

Please note: I really don't think this is a good idea.

+3


source







All Articles