4

Python optparse 通常允许用户多次指定一个选项,并默默地忽略除最后一个选项之外的所有选项。例如,如果 option 的动作--foostore并且 option 的动作--flagstore_const, store_trueor store_false,则以下命令将是等效的:

my-command --foo=bar --foo=another --flag --foo=last --flag
my-command --flag --foo=last

(更新:argparse 默认做同样的事情。)

现在,我有很多选项,并且多次指定它们中的任何一个都没有意义。如果用户多次指定相同的选项,我想警告他们可能出现的错误。

检测多次指定的选项的最优雅方法是什么?请注意,相同的选项可以有短格式、长格式和缩写长格式(因此、 和-f都是--foobar相同的选项)。如果能够检测到同时指定具有相同目的地的多个选项的情况会更好,这样如果用户同时指定了两个选项并且两个选项都将值存储到相同的目的地并且有效地存储了一个值,则可以发出警告互相覆盖。--foob--foo--quiet--verbose

更新:为了更加用户友好,警告应该引用命令行上使用的确切选项名称。使用append动作代替store是可能的,但是当我们检测到冲突时,我们不能说是哪个选项导致了它(是它-q还是--verbose--quiet --quiet)。

不幸的是,我坚持使用 optparse,无法使用 argparse,因为我必须支持 Python 2.6。

PS 如果您知道仅适用于 argparse 的解决方案,请也发布它。虽然我尽量减少外部依赖项的数量,但在 Python 2.6 下使用 argparse 仍然是一种选择。

4

2 回答 2

1

您可以使用action="append"( optparse) 然后检查附加元素的数量。请参阅http://docs.python.org/library/optparse.html#other-actions

于 2012-09-17T14:30:09.667 回答
1

我认为正确的方法是以某种方式“定义你的行为”。

例如,您可以使用该操作callback并实现一个实现所需行为的函数。您可以编写一个函数,首先检查目标是否已填充,如果已填充,则将重叠选项存储到列表中。解析完成后,您应该检查这些列表是否为空,如果它们没有引发适当的异常。

另一种方法是定义您自己的操作。你可以看看这里

一个使用回调的小例子:

import sys
import functools
from optparse import OptionParser


bad_option = 'BAD OPTION'

def store(option, opt, value, parser, dest, val):
    """Set option's destination *dest* to *val*  if there are no conflicting options."""
    list_name = dest + '_options_list'
    try:
        # if this option is a conflict, save its name and set the value to bad_option
        getattr(parser.values, list_name).append(opt)
        setattr(parser.values, dest, bad_option)
    except AttributeError:
        # no conflicts, set the option value and add the options list
        setattr(parser.values, dest, val)
        setattr(parser.values, list_name, [opt])

store_true = functools.partial(store, val=True)
store_false = functools.partial(store, val=False)


parser = OptionParser()
parser.add_option('-v', '--verbose',
                  action='callback', callback=store_true,
                  help='Increase output verbosity',
                  callback_kwargs={'dest': 'verbose'})

parser.add_option('-q', '--quiet',
                  action='callback', callback=store_false,
                  help='Decrease output verbosity',
                  callback_kwargs={'dest': 'verbose'})

opts, args = parser.parse_args()

# detects all conflicting options for all destinations
found = False
for dest in ('verbose',):
    if getattr(opts, dest) == bad_option:
        conflicting_opts = ', '.join(getattr(opts, dest + '_options_list'))
        print('Conflicting options %s for destination %s'
              % (conflicting_opts, dest))
        found = True

if found:
    parser.print_usage()
    sys.exit(2)

和输出:

$ python testing_optparse.py -v -q
Conflicting options -v, -q for destination verbose
Usage: prova_optparse.py [options]

可能最好OptionValueError在检测冲突时提出一个,即使这将只允许获得几个冲突的选项。如果你想获得所有冲突的选项,你必须解析剩余的参数(in parser.rargs)。

于 2012-09-17T18:11:57.647 回答