I'm trying to group arguments such that the user can do either:
python sample.py scan -a 1 -b 2
or
python sample.pt save -d /tmp -n something
here is my code:
import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser(
            description='this is the description'
            )
    parser.add_argument('op', choices=['scan','save'], help='operation', default='scan')
    root_group = parser.add_mutually_exclusive_group()
    group1 = root_group.add_argument_group('g1', 'scan')
    group1.add_argument('-a', help='dir1')
    group1.add_argument('-b', help='dir2')
    group2 = root_group.add_argument_group('g2', 'save')
    group2.add_argument('-d', help='dir')
    group2.add_argument('-n', help='name')
    args = parser.parse_args()
    print args
as I run python sample.py --help
I'm getting an error. Can someone please tell me how to fix it?
Traceback (most recent call last):
  File "sample.py", line 18, in <module>
    args = parser.parse_args()
  File "C:\Python27\lib\argparse.py", line 1688, in parse_args
    args, argv = self.parse_known_args(args, namespace)
  File "C:\Python27\lib\argparse.py", line 1720, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
  File "C:\Python27\lib\argparse.py", line 1926, in _parse_known_args
    start_index = consume_optional(start_index)
  File "C:\Python27\lib\argparse.py", line 1866, in consume_optional
    take_action(action, args, option_string)
  File "C:\Python27\lib\argparse.py", line 1794, in take_action
    action(self, namespace, argument_values, option_string)
  File "C:\Python27\lib\argparse.py", line 994, in __call__
    parser.print_help()
  File "C:\Python27\lib\argparse.py", line 2313, in print_help
    self._print_message(self.format_help(), file)
  File "C:\Python27\lib\argparse.py", line 2287, in format_help
    return formatter.format_help()
  File "C:\Python27\lib\argparse.py", line 279, in format_help
    help = self._root_section.format_help()
  File "C:\Python27\lib\argparse.py", line 209, in format_help
    func(*args)
  File "C:\Python27\lib\argparse.py", line 317, in _format_usage
    action_usage = format(optionals + positionals, groups)
  File "C:\Python27\lib\argparse.py", line 388, in _format_actions_usage
    start = actions.index(group._group_actions[0])
IndexError: list index out of range
and if I add action='store_const', the error goes away and a new error occurrs asking for 4 inputs.
The store_true option automatically creates a default value of False. Likewise, store_false will default to True when the command-line argument is not present. The source for this behavior is succinct and clear: http://hg.python.org/cpython/file/2.7/Lib/argparse.py#l861.
action defines how to handle command-line arguments: store it as a constant, append into a list, store a boolean value etc. There are several built-in actions available, plus it's easy to write a custom one. The one with - is an optional argument, see docs.
parser. add_argument('indir', type=str, help='Input dir for videos') created a positional argument. For positional arguments to a Python function, the order matters. The first value passed from the command line becomes the first positional argument. The second value passed becomes the second positional argument.
parse_args() returns two values: options, an object containing values for all of your options— e.g. if "--file" takes a single string argument, then options. file will be the filename supplied by the user, or None if the user did not supply that option.
Argparse does not seem to fully support adding a group into another group. This error happens because Argparse requires root_group to have some kind of action. A workaround would be adding an argument to the group:
import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser(
            description='this is the description'
            )
    # This is now redundant. We can remove it
    # parser.add_argument('op', choices=['scan','save'], help='operation', default='scan')
    root_group = parser.add_mutually_exclusive_group()
    # Workaround
    root_group.add_argument('--scan', help='scan', action='store_true')
    root_group.add_argument('--save', help='save', action='store_true')
    group1 = root_group.add_argument_group('g1', 'scan')
    group2 = root_group.add_argument_group('g2', 'save')
    group1.add_argument('-a', help='dir1')
    group1.add_argument('-b', help='dir2')
    group2.add_argument('-d', help='dir', default='')
    group2.add_argument('-n', help='name')
    args = parser.parse_args()
    print args 
Notice that we are using --scan and --save. To avoid using the -- prefix, you may need the help of Sub-commands. Details can be found here.
Thanks to @skyline's link above, I got it working with subparsers:
import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser(
            description='this is the description'
            )
    scan_parser = argparse.ArgumentParser(add_help=False)
    scan_parser.add_argument('-a', '--a', help='first num', required=True)
    scan_parser.add_argument('-b', '--b', help='second num', required=True)
    save_parser = argparse.ArgumentParser(add_help=False)
    save_parser.add_argument('-d', '--d', help='directory path', required=True)
    save_parser.add_argument('-n', '--n', help='name of the file', required=True)
    sp = parser.add_subparsers()
    sp_scan = sp.add_parser('scan', parents=[scan_parser], help='scans directories')
    sp_save = sp.add_parser('save', parents=[save_parser], help='saves something')
    args = parser.parse_args()
    print args
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With