Argparse: Required arguments listed under “optional arguments”?

后端 未结 4 460
暗喜
暗喜 2020-12-12 09:02

I use the following simple code to parse some arguments; note that one of them is required. Unfortunately, when the user runs the script without providing the argument, the

相关标签:
4条回答
  • 2020-12-12 09:11

    Building off of @Karl Rosaen

    parser = argparse.ArgumentParser()
    optional = parser._action_groups.pop() # Edited this line
    required = parser.add_argument_group('required arguments')
    # remove this line: optional = parser...
    required.add_argument('--required_arg', required=True)
    optional.add_argument('--optional_arg')
    parser._action_groups.append(optional) # added this line
    return parser.parse_args()
    

    and this outputs:

    usage: main.py [-h] [--required_arg REQUIRED_ARG]
               [--optional_arg OPTIONAL_ARG]
    
    required arguments:
      --required_arg REQUIRED_ARG
    
    optional arguments:
      -h, --help                    show this help message and exit
      --optional_arg OPTIONAL_ARG
    
    0 讨论(0)
  • 2020-12-12 09:26

    Parameters starting with - or -- are usually considered optional. All other parameters are positional parameters and as such required by design (like positional function arguments). It is possible to require optional arguments, but this is a bit against their design. Since they are still part of the non-positional arguments, they will still be listed under the confusing header “optional arguments” even if they are required. The missing square brackets in the usage part however show that they are indeed required.

    See also the documentation:

    In general, the argparse module assumes that flags like -f and --bar indicate optional arguments, which can always be omitted at the command line.

    Note: Required options are generally considered bad form because users expect options to be optional, and thus they should be avoided when possible.

    That being said, the headers “positional arguments” and “optional arguments” in the help are generated by two argument groups in which the arguments are automatically separated into. Now, you could “hack into it” and change the name of the optional ones, but a far more elegant solution would be to create another group for “required named arguments” (or whatever you want to call them):

    parser = argparse.ArgumentParser(description='Foo')
    parser.add_argument('-o', '--output', help='Output file name', default='stdout')
    requiredNamed = parser.add_argument_group('required named arguments')
    requiredNamed.add_argument('-i', '--input', help='Input file name', required=True)
    parser.parse_args(['-h'])
    
    usage: [-h] [-o OUTPUT] -i INPUT
    
    Foo
    
    optional arguments:
      -h, --help            show this help message and exit
      -o OUTPUT, --output OUTPUT
                            Output file name
    
    required named arguments:
      -i INPUT, --input INPUT
                            Input file name
    
    0 讨论(0)
  • 2020-12-12 09:27

    Since I prefer to list required arguments before optional, I hack around it via:

        parser = argparse.ArgumentParser()
        parser._action_groups.pop()
        required = parser.add_argument_group('required arguments')
        optional = parser.add_argument_group('optional arguments')
        required.add_argument('--required_arg', required=True)
        optional.add_argument('--optional_arg')
        return parser.parse_args()
    

    and this outputs:

    usage: main.py [-h] [--required_arg REQUIRED_ARG]
                   [--optional_arg OPTIONAL_ARG]
    
    required arguments:
      --required_arg REQUIRED_ARG
    
    optional arguments:
      --optional_arg OPTIONAL_ARG
    

    I can live without 'help' showing up in the optional arguments group.

    0 讨论(0)
  • 2020-12-12 09:35

    One more time, building off of @RalphyZ

    This one doesn't break the exposed API.

    from argparse import ArgumentParser, SUPPRESS
    # Disable default help
    parser = ArgumentParser(add_help=False)
    required = parser.add_argument_group('required arguments')
    optional = parser.add_argument_group('optional arguments')
    
    # Add back help 
    optional.add_argument(
        '-h',
        '--help',
        action='help',
        default=SUPPRESS,
        help='show this help message and exit'
    )
    required.add_argument('--required_arg', required=True)
    optional.add_argument('--optional_arg')
    

    Which will show the same as above and should survive future versions:

    usage: main.py [-h] [--required_arg REQUIRED_ARG]
               [--optional_arg OPTIONAL_ARG]
    
    required arguments:
      --required_arg REQUIRED_ARG
    
    optional arguments:
      -h, --help                    show this help message and exit
      --optional_arg OPTIONAL_ARG
    
    0 讨论(0)
提交回复
热议问题