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