Search code examples
pythonpython-2.7python-3.xoptparse

how to modify nargs( of optparse-add_option) from User input(raw_input)?


This Question is continuation of old question @: how to access nargs of optparse-add_action?

As that question was answered for what it was in-tented.

Brief:

Suppose if I am using add_option utility like below:

parser.add_option('-c','--categories', dest='Categories', nargs=4 )

Is there a way to modify nargs of add_option() from user input using raw_input.?

EDIT: I will give a clear difference between my "previous question need" and "this question need".

First question case:

My script will ask for user inputs if user has provided no inputs, i.e.,He has just run

#./commandparser.py

Second Question case requirement is:

when i run my script ./commandparser.py -c abc bac cad it throws error: commandparser.py: error: -c option requires 4 arguments and exit the script.

Instead of throwing error and exit the script. I want some mechanism so that it asks user to input remaining arguments i.e., 4th argument without exiting the script.


Solution

  • Are you, by any chance, trying to accept a variable number of values for this option? That is, use the 'rawinput' to set nargs, which is then used to parse the command line?

    The optparse documentation has an example of using a custom callback to handle a variable number of values:

    https://docs.python.org/2/library/optparse.html#callback-example-6-variable-arguments

    argparse, on the other hand, does allow a variable number of values, with nargs values like '?' (0 or 1), '+' (1 or more), '*' (0 or more).


    Since I'm more conversant with argparse I'll sketch out an interactive script to handle your revised requirement:

    import argparse
    parser = argparse.ArgumentParser(prog='PROG')
    parser.add_argument('-c', '--categories', nargs='+', help='4 categories', default=[])
    args = parser.parse_args()
    print(args)
    categories = args.categories
    while len(categories)<4:
        print(parser.format_usage())
        x = raw_input('enter %s categories: '%(4-len(categories))).split()
        categories.extend(x)
    print('categories', categories)
    

    If 'categories' are the only arguments, you could replace all of the argparse stuff (or optparse) with categories = sys.argv[1:], or [2:] if you still expect the '-c' flag.


    Or using optparse (adapted from the docs example for variable length callback):

    def vararg_callback(option, opt_str, value, parser):
         value = []
         for arg in parser.rargs:
             # stop on --foo like options
             if arg[:2] == "--" and len(arg) > 2:
                 break
             # stop on -a (ignore the floats issue)
             if arg[:1] == "-" and len(arg) > 1:
                 break
             value.append(arg)
         del parser.rargs[:len(value)]
         setattr(parser.values, option.dest, value)
    
    def use_opt():
        import optparse
        parser = optparse.OptionParser()
        parser.add_option('-c','--categories', dest='categories', action="callback", callback=vararg_callback)
        (options, args) = parser.parse_args()
        print options, args
        return options, args, parser
    
    args, rest, parser = use_opt()