With Python's optparse module, how do you create an option that takes a variable number of arguments?

后端 未结 6 2162
终归单人心
终归单人心 2021-02-13 19:38

With Perl\'s Getopt::Long you can easily define command-line options that take a variable number of arguments:

foo.pl --files a.txt             --ve         


        
相关标签:
6条回答
  • 2021-02-13 20:11

    This took me a little while to figure out, but you can use the callback action to your options to get this done. Checkout how I grab an arbitrary number of args to the "--file" flag in this example.

    from optparse import OptionParser,
    
    def cb(option, opt_str, value, parser):
            args=[]
            for arg in parser.rargs:
                    if arg[0] != "-":
                            args.append(arg)
                    else:
                            del parser.rargs[:len(args)]
                            break
            if getattr(parser.values, option.dest):
                    args.extend(getattr(parser.values, option.dest))
            setattr(parser.values, option.dest, args)
    
    parser=OptionParser()
    parser.add_option("-q", "--quiet",
            action="store_false", dest="verbose",
            help="be vewwy quiet (I'm hunting wabbits)")
    parser.add_option("-f", "--filename",
            action="callback", callback=cb, dest="file")
    
    (options, args) = parser.parse_args()
    
    print options.file
    print args
    

    Only side effect is that you get your args in a list instead of tuple. But that could be easily fixed, for my particular use case a list is desirable.

    0 讨论(0)
  • 2021-02-13 20:15

    Here's one way: Take the fileLst generating string in as a string and then use http://docs.python.org/2/library/glob.html to do the expansion ugh this might not work without escaping the *

    Actually, got a better way: python myprog.py -V -l 1000 /home/dominic/radar/*.json <- If this is your command line

    parser, opts = parse_args()

    inFileLst = parser.largs

    0 讨论(0)
  • 2021-02-13 20:17

    My mistake: just found this Callback Example 6.

    0 讨论(0)
  • 2021-02-13 20:20

    I believe optparse does not support what you require (not directly -- as you noticed, you can do it if you're willing to do all the extra work of a callback!-). You could also do it most simply with the third-party extension argparse, which does support variable numbers of arguments (and also adds several other handy bits of functionality).

    This URL documents argparse's add_argument -- passing nargs='*' lets the option take zero or more arguments, '+' lets it take one or more arguments, etc.

    0 讨论(0)
  • 2021-02-13 20:20

    Wouldn't you be better off with this?

    foo.pl --files a.txt,b.txt,c.txt --verbose
    
    0 讨论(0)
  • 2021-02-13 20:31

    I recently has this issue myself: I was on Python 2.6 and needed an option to take a variable number of arguments. I tried to use Dave's solution but found that it wouldn't work without also explicitly setting nargs to 0.

    def arg_list(option, opt_str, value, parser):
        args = set()
        for arg in parser.rargs:
            if arg[0] == '-':
                break
            args.add(arg)
            parser.rargs.pop(0)
        setattr(parser.values, option.dest, args)
    
    parser=OptionParser()
    parser.disable_interspersed_args()
    parser.add_option("-f", "--filename", action="callback", callback=arg_list,
                      dest="file", nargs=0)
    
    (options, args) = parser.parse_args()
    

    The problem was that, by default, a new option added by add_options is assumed to have nargs = 1 and when nargs > 0 OptionParser will pop items off rargs and assign them to value before any callbacks are called. Thus, for options that do not specify nargs, rargs will always be off by one by the time your callback is called.

    This callback is can be used for any number of options, just have callback_args be the function to be called instead of setattr.

    0 讨论(0)
提交回复
热议问题