2015-02-05 101 views
0

我在OptionParser的选项,如下图所示:Python的OptionParser允许选择类型选择多个参数

foo_choices = ['foo', 'bar', 'mac', 'win'] 
    parser.add_option('-t', '--test', 
        type='choice', 
        action='store', 
        dest='test', 
        choices=foo_choices, 
        default='foo') 

但是,我想要的选项,以便能够采取多个选项(可以是逗号分隔或允许> 1个参数)。只要设置nargs = 2可以在多个参数中通过,所以我认为这可以用于类型选择。我无法弄清楚如何做到可变数量的nargs。

语法,如:

./demo.py -t foo -o out.out 
./demo.py -t foo,bar -o out.out 

或者

./demo.py -t foo -o out.out 
./demo.py -t foo bar -o out.out 

我使用回调拆就逗号试过,但如果回调函数返回一个数组,它的错误,因为该选项是无效选择'foo,bar'。错误是有道理的,但我不确定从哪里去。

def foo_callback(option, opt, value, parser): 
    setattr(parser.values, option.dest, value.split(',')) 

试图去为NARGS办法,我尝试推行Callback Example 6

#!/usr/bin/python 

from optparse import OptionParser 

def main(): 
    parser = OptionParser() 
    foo_choices = ['foo', 'bar', 'mac', 'win'] 
    parser.add_option('-t', '--test', 
        type='choice', 
        action='callback', 
        dest='test', 
        choices=foo_choices, 
        callback=vararg_callback) 
    (options, args) = parser.parse_args() 

    print options 
    print args 

def vararg_callback(option, opt_str, value, parser): 
    assert value is None 
    value = [] 

    def floatable(str): 
     try: 
      float(str) 
      return True 
     except ValueError: 
      return False 

    for arg in parser.rargs: 
     # stop on --foo like options 
     if arg[:2] == "--" and len(arg) > 2: 
      break 
     # stop on -a, but not on -3 or -3.0 
     if arg[:1] == "-" and len(arg) > 1 and not floatable(arg): 
      break 
     value.append(arg) 

    del parser.rargs[:len(value)] 
    setattr(parser.values, option.dest, value)  

if __name__ == '__main__': 
    main() 

这个片段介绍了一种可以实现可变数量NARGS的。然而,我得到这个工作的唯一方法是从我的选项中删除类型和选择(击败我试图做的目的)。如果我没有,我会得到错误的是:

[[email protected] a]$ ./demo.py -t foo 
Traceback (most recent call last): 
    File "./demo.py", line 43, in <module> 
    main() 
    File "./demo.py", line 14, in main 
    (options, args) = parser.parse_args() 
    File "/usr/lib64/python2.6/optparse.py", line 1394, in parse_args 
    stop = self._process_args(largs, rargs, values) 
    File "/usr/lib64/python2.6/optparse.py", line 1438, in _process_args 
    self._process_short_opts(rargs, values) 
    File "/usr/lib64/python2.6/optparse.py", line 1545, in _process_short_opts 
    option.process(opt, value, values, self) 
    File "/usr/lib64/python2.6/optparse.py", line 788, in process 
    self.action, self.dest, opt, value, values, parser) 
    File "/usr/lib64/python2.6/optparse.py", line 808, in take_action 
    self.callback(self, opt, value, parser, *args, **kwargs) 
    File "./demo.py", line 20, in vararg_callback 
    assert value is None 
AssertionError 
+0

可能的复制到http://stackoverflow.com/questions/2756062/optionparser-python-module-multiple-entries-of-same-variable – pmod 2015-02-05 21:21:04

+0

在上面的链接的答案之一,你可以找到考试ple https://docs.python.org/2/library/email-examples.html – pmod 2015-02-05 21:23:12

+1

Just quick FYI,['optparse' is deprecated for'argparse'](http://stackoverflow.com/questions/3217673/why-use-argparse-rather-optparse) – 2015-02-05 21:24:31

回答

1

只需使用action='append', default=[]而非目前设置的;不需要自定义回调。
然后,您可以指定倍数为:-t foo -t bar

如果您需要默认设置,则可以在此之后进行;即像
test = options.test or ['foo']

+0

正如另一条评论所述,我不希望用户不得不重复多次。语法应该尽可能简单,所以我宁愿保持它像“-t foo bar”或“-t foo,bar” – Shark 2015-02-05 21:37:36

0

我想你可以尝试从标准中获得自己的选项类只覆盖标准检查你的情况:

from optparse import Option, OptionParser, OptionValueError 

class MyOption(Option): 
    def check_value(option, opt, value): 
     for val in value.split(','): 
      if val not in option.choices: 
       choices = ", ".join(map(repr, option.choices)) 
       raise OptionValueError("option %s: invalid choice: %r (choose from %s)" % (opt, val, choices)) 
     return value 

parser = OptionParser(option_class=MyOption) 
foo_choices = ['foo', 'bar', 'mac', 'win'] 
parser.add_option('-t', '--test', 
      type='choice', 
      dest='test', 
      choices=foo_choices) 


(options, args) = parser.parse_args() 

print options 

输出:

./test1.py -t foo,bar,mac 
{'test': 'foo,bar,mac'} 
+0

@Shark只是好奇,你有没有试过这个解决方案? – pmod 2015-03-19 21:44:52

相关问题