argparse — requiring either 2 values or none for an optional argument

后端 未结 4 988
你的背包
你的背包 2021-02-06 01:07

I\'m trying to make an optional argument for a script that can either take no values or 2 values, nothing else. Can you accomplish this using argparse?

# desired         


        
相关标签:
4条回答
  • 2021-02-06 01:23

    You'll have to do your own error checking here. Accept 0 or more value, and reject anything other than 0 or 2:

    parser = argparse.ArgumentParser()
    parser.add_argument("-a", "--action", nargs='*', action="store", help="do some action")
    args = parser.parse_args()
    
    if args.action is not None and len(args.action) not in (0, 2):
        parser.error('Either give no values for action, or two, not {}.'.format(len(args.action)))
    

    Note that args.action is set to None when no -a switch was used:

    >>> import argparse
    >>> parser = argparse.ArgumentParser()
    >>> parser.add_argument("-a", "--action", nargs='*', action="store", help="do some action")
    _StoreAction(option_strings=['-a', '--action'], dest='action', nargs='*', const=None, default=None, type=None, choices=None, help='do some action', metavar=None)
    >>> args = parser.parse_args([])
    >>> args.action is None
    True
    >>> args = parser.parse_args(['-a'])
    >>> args.action
    []
    
    0 讨论(0)
  • 2021-02-06 01:36

    Have your option take a single, optional comma-separated string. You'll use a custom type to convert that string to a list and verify that it has exactly two items.

    def pair(value):
        rv = value.split(',')
        if len(rv) != 2:
            raise argparse.ArgumentParser()
        return rv
    
    parser.add_argument("-a", "--action", nargs='?',
                        type=pair, metavar='val1,val2',
                        help="do some action")
    print parser.parse_args()
    

    Then you'd use it like

    $ ./script.py -a
    Namespace(action=None)
    $ ./script.py -a val1,val2
    Namespace(action=['val1','val2'])
    $ ./script.py -a val1
    usage: tmp.py [-h] [-a [ACTION]]
    script.py: error: argument -a/--action: invalid pair value: 'val1'
    $ ./script.py -a val1,val2,val3
    usage: tmp.py [-h] [-a [ACTION]]
    script.py: error: argument -a/--action: invalid pair value: 'val1,val2,val3'
    

    You can adjust the definition of pair to use a different separator and to return something other than a list (a tuple, for example).

    The metavar provides a better indication that the argument to action is a pair of values, rather than just one.

    $ ./script.py -h
    usage: script.py [-h] [-a [val1,val2]]
    
    optional arguments:
      -h, --help            show this help message and exit
      -a [val1,val2], --action [val1,val2]
                            do some action
    
    0 讨论(0)
  • 2021-02-06 01:42

    Just handle that case yourself:

    parser.add_argument("-a", "--action", nargs='*', action="store", help="do some action")
    args = parser.parse_args()
    
    if args.action is not None:
        if len(args.action) not in (0, 2):
            parser.error('Specify no or two actions')
    
        # action was specified but either there were two actions or no action
    else:
        # action was not specified
    

    Of course you should update the help text in that case so that the user has a chance to know this before running into the error.

    0 讨论(0)
  • 2021-02-06 01:45

    How about the required argument:parser.add_argument("-a", "--action", nargs=2, action="store", help="do some action", required=False)

    0 讨论(0)
提交回复
热议问题