【问题标题】:Python OptionParser to allow multiple arguments for choice type optionPython OptionParser 允许选择类型选项的多个参数
【发布时间】:2015-04-05 21:15:12
【问题描述】:

我在 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()

这个 sn-p 引入了一种实现可变数量的 nargs 的方法。但是,我让它工作的唯一方法是从我的选项中删除类型和选择(违背了我想要做的事情的目的)。如果我没有,我会得到的错误是:

[vagrant@machine 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

【问题讨论】:

标签: python optionparser


【解决方案1】:

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

如果你需要一个默认值,你可以在之后做;即类似
test = options.test or ['foo']

【讨论】:

  • 正如另一条评论中提到的,我不希望用户必须重复 -t 多次。语法应该尽可能简单,所以我更喜欢像“-t foo bar”或“-t foo,bar”一样保留它
【解决方案2】:

我认为您可以尝试从标准派生自己的 Option 类,以覆盖您的案例的标准检查:

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'}

【讨论】:

    猜你喜欢
    • 2021-06-12
    • 2013-03-26
    • 1970-01-01
    • 2013-06-14
    • 2018-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多