Negative boolean options --no-whatever in optparse?
Asked Answered
D

1

8

With optparse, is there a simple way to define negative options, e.g., --no-cleanup?

I did it this way, but it's cumbersome and bug-prone, especially due to the None check which is easy to forget and leave out:

#!/bin/env python

from __future__ import print_function
import sys
import optparse

def main(argv):
    parser = optparse.OptionParser("usage: %prog [options]")
    parser.add_option("--no-cleanup",
                      dest = "cleanup",
                      action = "store_false",
                      help = "do cleanup at end?")

    (opts, args) = parser.parse_args()

    if opts.cleanup == None:
        opts.cleanup = True

    # do stuff ...

    if opts.cleanup:
        print("Cleaning up!", file = sys.stderr)
    else:
        print("Not cleaning up", file = sys.stderr)

if __name__ == "__main__":
    main(sys.argv[1:])

Ideally I'd like to do something like Getoptions::Long in Perl, where I can define an option cleanup as boolean and then it will automatically provide --cleanup and --no-cleanup and set my boolean variable accordingly.

Danieladaniele answered 29/3, 2012 at 22:12 Comment(6)
argparse has this functionality - or is that not an option?Cereal
@jterrace: I use Python v2.6, so I think I don't have argparse.Danieladaniele
@Frank, argparse runs on python2.6, it's just not in the standard library. If you have setuptools, easy_install argparse has always worked just fine for me.Disdain
@jterrace, I'm not completely sure that argparse has more functionality than optparse in this situation (although I would still highly recommend it above optparse).Disdain
And one other comment...generally it is better practice to use the is operator when testing for None since None is a singleton. (That way user defined classes which override __eq__ are guaranteed to not evaluate to True) -- in other words myclassinstance == None could potentially be True whereas myclassinstance is None will never be.Disdain
Thanks everyone! I installed argparse using pip-python now.Danieladaniele
D
4

If I was to do this using optparse (or argparse for that matter -- assuming you want to add a --cleanup and --no-cleanup flag in one command), I would just subclass the option parser class... Something like:

from optparse import OptionParser
class MyOptParse(OptionParser):
      def boolean(self,dest,**kwargs):
          self.add_option('--%s'%dest,dest=dest,action='store_true',**kwargs)
          self.add_option('--no-%s'%dest,dest=dest,action='store_false',**kwargs)

Of course, this is a complete hack, but I think it's pretty obvious where I'm going with it...You can make boolean behave however you want it to (reformatting help, accepting a default value so that either '--blah' or '--no-blah' is set as the default, etc...)

I think that

parser=MyOptParse()
parser.boolean('cleanup',default=True,help="Do/Do Not do cleanup")

should work and get rid of the if options.cleanup is None line while it's at it since the default is set, although the help message will be repeated (with the code I provided)

If you just want to add defaults for a particular flag (to get rid of the check for None), you can use the default keyword to add_option, OR, according to the optparse documentation ...

A clearer way to specify default values is the set_defaults() method of OptionParser, which you can call at any time before calling parse_args(): e.g. parser.set_defaults(verbose=True)

Disdain answered 29/3, 2012 at 22:31 Comment(1)
you should add a .replace('-', '_') in dest argument. Is is possibile to condense the help, to avoid redundances, as in man gcc?Ubiquitous

© 2022 - 2024 — McMap. All rights reserved.