How to know if optparse option was passed in the command line or as a default
Asked Answered
F

3

8

Using python optparse.py, is there a way to work out whether a specific option value was set from the command line or from the default value.

Ideally I would like to have a dict just like defaults, but containing the options actually supplied from command line

I know that you could compare the value for each option with defaults, but this wouldn't distinguish a value was passed through command line which matched the default.

Thanks!


EDIT

Sorry my original phrasing wasn't very clear.

I have a large number of scripts which are called from batch files. For audit purposes, I would like to report on the options being passed, and whether they are passed from command line, default, or some other means, to a log file.

Using defaults you can tell whether an option matches a default value, but that still doesn't tell you whether it was actually supplied from command line. This can be relevant: if an option is passed from command line and agrees with the default, if you then change the default in the code the script will still get the same value.

To me it would feel quite natural to have an equivalent to defaults, containing the values actually supplied.

To make the question concrete, in this example:

>>> sys.argv = ['myscript.py','-a','xxx']
>>> import optparse
>>> parser = optparse.OptionParser()
>>> parser.add_option('-a', default = 'xxx')
>>> parser.add_option('-b', default = 'yyy')

How do I know that option a was passed from command line. Is the only way to parse the command line manually?

(I know this is a fairly minor point, but I thought it would be worth asking in case I'm missing smthing on optparse)

Thanks again

Foggia answered 7/4, 2010 at 14:27 Comment(3)
But isn't the point of a default to prevent you from having to worry what options were passed - regarless whether they match the defaults or not ?Agitprop
Perhaps this means you need another option?Psoriasis
please see my edit, this is about auditing, so it does make a difference how the script was called.Foggia
T
8

Instead of the below boilerplate code:

opts, args = parser.parse_args()

if you use the below code, you will have an additional values object opts_no_defaults with options that were explicitly specified by the user:

opts_no_defaults = optparse.Values()
__, args = parser.parse_args(values=opts_no_defaults)
opts = Values(parser.get_default_values().__dict__)
opts._update_careful(opts_no_defaults.__dict__)

At the end, opts should be identical as in the initial boilerplate code.

print opts_no_defaults.__dict__
print opts.__dict__
for opt in parser._get_all_options():
    if opt.dest:
        print "Value of %s: %s" % (opt._long_opts[0], getattr(opts, opt.dest))
        print "Is %s specified by user? %s" % (opt._long_opts[0], hasattr(opt_no_defaults, opt.dest))
Traynor answered 2/7, 2012 at 17:55 Comment(1)
Really nice! I was considering to create a custom OptionParser.get_default_values() that returned a custom Values to keep track of whether the value has a default or not.Tayyebeb
R
3

Not knowing you code is impossible to give the better answer, but...

  1. simply don't pass defaults to the parser and check for None values. A None value is a default for optparse lib so you can retrieve your own default and act as usually;

  2. extend optparse to specialize it.

I don't know your program but usually it is not a good design changing behavior when the configuration is the same.

Record answered 7/4, 2010 at 14:54 Comment(0)
P
1
def is_opt_provided (parser, dest):
   if any (opt.dest == dest and (opt._long_opts[0] in sys.argv[1:] or opt._short_opts[0] in sys.argv[1:]) for opt in parser._get_all_options()):
      return True
   return False    

Usage:

parser = OptionsParser()
parser.add_option('-o', '--opt', dest='opt_var', ...)

if is_opt_provided(parser, 'opt_var'):
   print "Option -o or --opt has been provided"

It would be great if Python maintainers included the suggested function to OptionParser class.

Presnell answered 2/5, 2014 at 17:37 Comment(1)
This is highly unreliable as it would return false +ve even if the option string matches something in arguments.Tayyebeb

© 2022 - 2024 — McMap. All rights reserved.