Search code examples
pythonvalidationoptparse

optparse(): Input validation


My apology in advance if it's already answered somewhere; I've been in the python site since last hr. but didn't quite figure out how I can I do this. My script should take the options like this:

myScript.py -f <file-name> -e [/ -d]
myScript.py -s <string> -e [/ -d]
myScript.py -f <file-name> [/ -s <string>] -e -w [<file_name>]

i.e. -f/-s,-e/-d are mandatory options but -f&-s cannot be used together and the same as with -e&-d options - cannot be used together. How can I put the check in place?

Another question, if I may ask at the same time: How can I use -w option (when used) with or w/o a value? When no value is supplied, it should take the default value otherwise the supplied one. Any help greatly appreciated. Cheers!!


Solution

  • It's been a while since I did anything with optparse, but I took a brief look through the docs and an old program.

    "-f/-s,-e/-d are mandatory options but -f&-s cannot be used together and the same as with -e&-d options - cannot be used together. How can I put the check in place?"

    For mutual exclusivity, you have to do the check yourself, for example:

    parser.add_option("-e", help="e desc", dest="e_opt", action="store_true")
    parser.add_option("-d", help="d desc", dest="d_opt", action="store_true")
    (opts, args) = parser.parse_args()
    if (parser.has_option("-e") and parser.has_option("-d")):
        print "Error!  Found both d and e options.  You can't do that!"
        sys.exit(1)
    

    Since the example options here are boolean, you could replace the if line above with:

    if (opts.e_opt and opts.d_opt):
    

    See the section How optparse handles errors for more.

    "How can I use -w option (when used) with or w/o a value?"

    I've never figured out a way to have an optparse option for which a value is, well, optional. AFAIK, you have to set the option up to have values or to not have values. The closest I've come is to specify a default value for an option which must have a value. Then that entry doesn't have to be specified on the command line. Sample code :

    parser.add_option("-w", help="warning", dest="warn", default=0)
    

    An aside with a (hopefully helpful) suggestion:

    If you saw the docs, you did see the part about how "mandatory options" is an oxymoron, right?    ;-p    Humor aside, you may want to consider re-designing the interface, so that:

    • Required information isn't entered using an "option".
    • Only one argument (or group of arguments) enters data which could be mutually exclusive. In other words, instead of "-e" or "-d", have "-e on" or "-e off". If you want something like "-v" for verbose and "-q" for quiet/verbose off, you can store the values into one variable:
    parser.add_option("-v", help="verbose on", dest="verbose", action="store_true")
    parser.add_option("-q", help="verbose off", dest="verbose", action="store_false")
    

    This particular example is borrowed (with slight expansion) from the section Handling boolean (flag) options. For something like this you might also want to check out the Grouping Options section; I've not used this feature, so won't say more about it.