Here is an example code:
import argparse
parser=argparse.ArgumentParser()
parser.add_argument('-main_arg')
subparser=parser.add_subparser()
a=subparser.add_parser('run')
a.add_argument('required_sub_arg')
a.add_argument('arg_a')
b=subparser.add_parser('b')
parser.parse_args()
I want it to read in -main_arg
if I enter program run required_sub_arg -main_arg -arg_a
Right now, it doesn't recognize -main_arg
as a valid argument.
Adding arguments Later, calling parse_args() will return an object with two attributes, integers and accumulate . The integers attribute will be a list of one or more ints, and the accumulate attribute will be either the sum() function, if --sum was specified at the command line, or the max() function if it was not.
required is a parameter of the ArugmentParser object's function add_argument() . By default, the arguments of type -f or --foo are optional and can be omitted. If a user is required to make an argument, they can set the keyword argument required to True .
To add an optional argument, simply omit the required parameter in add_argument() . args = parser. parse_args()if args.
As this question still has visits in 2018, before doing anything this complex with argparse, please consider using docopt or click instead. It will improve both your sanity and that of anyone who might read or modify your code. Thank you.
As is, you have a few issues.
First, parser.parse_args
is a method that returns a namespace of parser
's arguments, so you should do something like
args = parser.parse_args()
Then args.main_args
to get-main_arg
from a call like
program -main_arg run required_sub_arg -arg_a
Your issue with main_arg
is that you have created a argument to parser
named main_arg
, and you make a call like
program run required_sub_arg -main_arg -arg_a
that refers to an argument to a
named main_arg
. Since a
doesn't have such an argument, it is invalid.
In order to refer to a parser's argument from one of its subparser, you have to make said subparser inherit the arguments of its parent. This is done with
a=parser.add_subparser('run', parents=[parser])
You have mistaken subparser for child parser. See http://docs.python.org/dev/py3k/library/argparse.html and https://code.google.com/p/argparse/issues/detail?id=54 for more informations.
For anyone else using argparse that arrives here looking for a way to display "common" sub-parser arguments in the "main" help screen, here's one approach:
import argparse
common = argparse.ArgumentParser(add_help=False)
common.add_argument('--shared', action='store_true', help='some shared arg')
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('--parent', action='store_true', help='parent only arg')
subparsers = parser.add_subparsers()
run = subparsers.add_parser('run', parents=[common])
run.add_argument('--fast', action='store_true', help='run only arg')
parser.epilog = "--- Arguments common to all sub-parsers ---" \
+ common.format_help().replace(common.format_usage(), '')
args = parser.parse_args()
Main help:
$ program.py -h
usage: program.py [-h] {run} ...
positional arguments:
{run}
optional arguments:
-h, --help show this help message and exit
--parent parent only arg
--- Arguments common to all sub-parsers ---
optional arguments:
--shared some shared arg
run
sub-parser help:
$ program.py run -h
usage: program.py run [-h] [--shared]
optional arguments:
-h, --help show this help message and exit
--shared some shared arg
--fast run only arg
To address the actual question, since the accepted answer doesn't run for me, here's some additional information on why it doesn't seem possible to truly share argparse arguments with the same name across both parent and child/sub-parser parsers.
First, the problem with the following code:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-main_arg')
subparsers = parser.add_subparsers()
run = subparsers.add_parser('run', parents=[parser])
args = parser.parse_args()
Is that it leads to the following error, because both parent parser
and sub-parser run
define the -h/--help argument (by default).
Argparse.ArgumentError: argument -h/--help: conflicting option strings: -h, --help
While this error can be avoided by suppressing the -h/--help option (with add_help=False
) on either the parent or the child, it's nice to have the help option at both levels.
Another potential way to avoid conflicting help options is to move common arguments to a shared parser, common
:
import argparse
common = argparse.ArgumentParser(add_help=False)
common.add_argument('-main_arg', action='store_true')
parser = argparse.ArgumentParser(parents=[common])
subparsers = parser.add_subparsers()
run = subparsers.add_parser('run', parents=[common])
args = parser.parse_args()
print(args)
While this appears to work on the surface, in practice, it doesn't work as intended:
$ program.py run # OK
Namespace(main_arg=False)
$ program.py run -main_arg # OK
Namespace(main_arg=True)
$ program.py -main_arg run # BAD: expected main_arg to be True
Namespace(main_arg=False)
The behavior observed when parsing program.py -main_arg run
illustrates a key relationship: a parent argparser and its sub-parsers are independent parsers, where the parent parses all arguments up to the sub-parser "command" positional argument, and then the selected sub-parser parses the remaining arguments in the same Namespace as the parent with no regard for attributes that may have been set by the parent.
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