python argparse store --foo = bar como args.key = 'foo', args.value = 'bar'

Eu gostaria de analisar uma linha de comando que tenha um grupo de opções mutuamente exclusivo. Normalmente, eu usaria--foo bar que produziria, no espaço de nomes,args.foo = 'bar'

No entanto, como todas essas opções são mutuamente exclusivas, e eu estou interessado no nome da opção e no argumento passado para a opção, e eu tenho várias dessas opções que precisam ser alimentadas a jusante, o que eu realmente gostaria é voltarargs.option_name = 'foo', args.option_value = 'bar' no meu espaço para nome em vez deargs.foo='bar'.

O que eu fiz é:

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)

quando executado, meu namespace será semelhante a:

Namespace(thing_key='--foo', thing='bar')

quando--foo=bar é analisado. Obviamente, infelizmente, se --foo ou --nar nunca é passado,namespace.thing_key não é definido, então eu tenho que usar umgetattr().

A substituição da ação, embora funcional, não parece realmente correta.

Suspeito que as mentes brilhantes por trás do argparse já tenham acertado de alguma forma, e só estou perdendo isso na documentação e na minha leitura do argparse.py.

Qual é a melhor maneira, certa, pitônica, de fazer isso? Subparsers? Estou usando python 3.5.

Então, acabei usando os dados de ambas as suas respostas para construir isso, que lida com a opção, seu argumento e define tudo de forma sutil no momento da inicialização.

Muito obrigado pelas dicas, pistas e validação. Estou surpreso que isso não tenha sido discutido antes e se tornado algo padronizado. istoé uma caixa de canto, mas não é uma caixa de cantoao usar opções mutuamente exclusivas.

    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)

questionAnswers(2)

yourAnswerToTheQuestion