我想解析一个具有互斥选项组的命令行。通常,我只会使用--foo bar
这会在命名空间中产生,args.foo = 'bar'
但是,由于所有这些选项都是互斥的,并且我对选项名称和传递给选项的参数都感兴趣,并且我有几个需要提供给下游的选项,所以我真正想要的是去取回args.option_name = 'foo', args.option_value = 'bar'
在我的命名空间中而不是args.foo='bar'
.
我所做的是:
class KeyAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
setattr(namespace, self.dest, values)
setattr(namespace, self.dest+'_key', option_string)
frob = parser.add_mutually_exclusive_group()
frob.add_argument('--foo', dest='thing', nargs='?', action=KeyAction)
frob.add_argument('--nar', dest='thing', nargs='?', action=KeyAction)
运行时,我的命名空间将如下所示:
Namespace(thing_key='--foo', thing='bar')
when --foo=bar
被解析。当然,遗憾的是,如果 --foo 或 --nar 从未传入,namespace.thing_key
没有被定义,所以我必须使用getattr()
.
动作覆盖虽然有效,但似乎不太正确。
我怀疑 argparse 背后的聪明人已经以某种方式正确地实现了这一点,而我只是在文档和我的文档中遗漏了它
读取 argparse.py。
最好的、正确的、Pythonic 的方法是什么?子解析器?
我正在使用 python 3.5。
因此,我最终使用了您两个答案中的数据来构建这个,它处理选项、它的参数,并在初始化时合理地设置所有内容。
非常感谢您的提示、线索和验证。我很惊讶这之前没有出现在 argparse 中并成为标准化的东西。它is一个极端情况,但并不是那么极端的情况当使用互斥选项时.
class ValueAction(argparse.Action):
"""Override to store both the format type as well as the argument"""
# pylint: disable=too-few-public-methods
def __init__(self, option_strings, dest, **kwargs):
self._dest = dest
dest = dest + '_arguments'
container = kwargs.pop('container')
kwargs['action'] = kwargs.pop('subaction')
action_class = container._pop_action_class(kwargs)
if not callable(action_class):
raise ValueError('unknown action "%s"' % (action_class,))
self._action = action_class(option_strings, dest, **kwargs)
super().__init__(option_strings, dest, **kwargs)
def __call__(self, parser, namespace, values, option_string=None):
self._action(parser, namespace, values, option_string)
if isinstance(option_string, str):
while option_string[0] in parser.prefix_chars:
option_string = option_string[1:]
setattr(namespace, self._dest, option_string)