argparse, tell if arg was defaulted

Robert Kern robert.kern at gmail.com
Tue Mar 15 15:19:15 EDT 2011


On 3/15/11 12:46 PM, Neal Becker wrote:
> Robert Kern wrote:
>
>> On 3/15/11 9:54 AM, Neal Becker wrote:
>>> Is there any way to tell if an arg value was defaulted vs. set on command
>>> line?
>>
>> No. If you need to determine that, don't set a default value in the
>> add_argument() method. Then just check for None and replace it with the
>> default value and do whatever other processing for the case where the user
>> does not specify that argument.
>>
>> parser.add_argument('-f', '--foo', help="the foo argument [default: bar]")
>>
>> args = parser.parse_args()
>> if args.foo is None:
>>       args.foo = 'bar'
>>       print 'I'm warning you that you did not specify a --foo argument.'
>>       print 'Using default=bar.'
>>
>
> Not a completely silly use case, actually.  What I need here is a combined
> command line / config file parser.
>
> Here is my current idea:
> -----------------------------
>
> parser = OptionParser()
> parser.add_option ('--opt1', default=default1)
>
> (opt,args) = parser.parse_args()
>
> import json, sys
>
> for arg in args:
>      print 'arg:', arg
>      d = json.load(open (arg, 'r'))
>      parser.set_defaults (**d)
>
> (opt,args) = parser.parse_args()
> -----------------------
>
> parse_args() is called 2 times.  First time is just to find the non-option args,
> which are assumed to be the name(s) of config file(s) to read.  This is used to
> set_defaults.  Then run parse_args() again.

I think that would work fine for most cases. Just be careful with the argument 
types that may consume resources. E.g. type=argparse.FileType().

You could also make a secondary parser that just extracts the config-file argument:

[~]
|25> import argparse

[~]
|26> config_parser = argparse.ArgumentParser(add_help=False)

[~]
|27> config_parser.add_argument('-c', '--config', action='append')
_AppendAction(option_strings=['-c', '--config'], dest='config', nargs=None, 
const=None, default=None, type=None, choices=None, help=None, metavar=None)

[~]
|28> parser = argparse.ArgumentParser()

[~]
|29> parser.add_argument('-c', '--config', action='append')  # For the --help 
string.
_AppendAction(option_strings=['-c', '--config'], dest='config', nargs=None, 
const=None, default=None, type=None, choices=None, help=None, metavar=None)

[~]
|30> parser.add_argument('-o', '--output')
_StoreAction(option_strings=['-o', '--output'], dest='output', nargs=None, 
const=None, default=None, type=None, choices=None, help=None, metavar=None)

[~]
|31> parser.add_argument('other', nargs='*')
_StoreAction(option_strings=[], dest='other', nargs='*', const=None, 
default=None, type=None, choices=None, help=None, metavar=None)

[~]
|32> argv = ['-c', 'config-file.json', '-o', 'output.txt', 'other', 'arguments']

[~]
|33> known, unknown = config_parser.parse_known_args(argv)

[~]
|34> known
Namespace(config=['config-file.json'])

[~]
|35> unknown
['-o', 'output.txt', 'other', 'arguments']

[~]
|36> for cf in known.config:
...>     # Load d from file.
...>     parser.set_defaults(**d)
...>

[~]
|37> parser.parse_args(unknown)
Namespace(config=None, other=['other', 'arguments'], output='output.txt')


-- 
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
  that is made terrible by our own mad attempt to interpret it as though it had
  an underlying truth."
   -- Umberto Eco




More information about the Python-list mailing list