Multiple positional arguments with Python and argparse

后端 未结 4 1776
梦毁少年i
梦毁少年i 2021-02-01 14:53

I\'m trying to use argparse to parse the command line arguments for a program I\'m working on. Essentially, I need to support multiple positional arguments spread within the opt

4条回答
  •  无人共我
    2021-02-01 15:40

    srgerg was right about the definition of positional arguments. In order to get the result you want, You have to accept them as optional arguments, and modify the resulted namespace according to your need.

    You can use a custom action:

    class MyAction(argparse.Action):
        def __call__(self, parser, namespace, values, option_string=None):
    
            # Set optional arguments to True or False
            if option_string:
                attr = True if values else False
                setattr(namespace, self.dest, attr)
    
            # Modify value of "input" in the namespace
            if hasattr(namespace, 'input'):
                current_values = getattr(namespace, 'input')
                try:
                    current_values.extend(values)
                except AttributeError:
                    current_values = values
                finally:
                    setattr(namespace, 'input', current_values)
            else:
                setattr(namespace, 'input', values)
    
    parser = argparse.ArgumentParser()
    parser.add_argument('-a', nargs='+', action=MyAction)
    parser.add_argument('-b', nargs='+', action=MyAction)
    parser.add_argument('input', nargs='+', action=MyAction)
    

    And this is what you get:

    >>> parser.parse_args(['fileone', '-a', 'filetwo', '-b', 'filethree'])
    Namespace(a=True, b=True, input=['fileone', 'filetwo', 'filethree'])
    

    Or you can modify the resulted namespace like this:

    >>> import argparse
    >>> parser = argparse.ArgumentParser()
    >>> parser.add_argument('-a', nargs='+')
    >>> parser.add_argument('-b', nargs='+')
    >>> parser.add_argument('input', nargs='+')
    >>> result = parser.parse_args(['fileone', '-a', 'filetwo', '-b', 'filethree'])
    
    >>> inputs = []
    >>> inputs.extend(result.a)
    >>> inputs.extend(result.b)
    >>> inputs.extend(result.input)
    
    >>> modified = argparse.Namespace(
            a = result.a != [],
            b = result.b != [],
            input = inputs)
    

    And this is what you get:

    >>> modified
    Namespace(a=True, b=True, input=['filetwo', 'filethree', 'fileone'])
    

    However, both method result in less readable and less maintainable code. Maybe it's better to change the program logic and do it in a different way.

提交回复
热议问题