2

I am using the Argparse Module to parse command line options. I have a main script which calls either subscript A or subscript B. I now have a a subparser instance for A and B and the main parser instance which should contain info about variables that A and B need. Something like:

def __init__(self):
    parser = argparse.ArgumentParser("Parser")
    parser.addArgument('--input') #this should be availabe for A and B

    subparsers = parser.add_subparsers('Description')
    A_parser = subparsers.add_parser(A)
    A_paser.add_argument('--a_option')

    B_parser = parser.add_subparser('Description')
    B_parser.add_arguemnt('--b_option')

    args = parser.parse_args()

But if I use it like this, I can only change args.options via the --input option if I do not specify A or B on program call. Execution of

program.py A --input ./

or

program.py --input ./ A

both fail.

1 Answer 1

2

I think you messed up the example usage from the python documentation. I attempted to edit your code example, but there were so many typos that I gave up. Expecially the usage of add_subparsers() and add_parser() was mixed up.

The cleaned up (and self-contained) version of the code looks like this:

import argparse


parser = argparse.ArgumentParser("Parser")
parser.add_argument('--input') #this should be available for A and B

subparsers = parser.add_subparsers(help='Description')
A_parser = subparsers.add_parser('A')
A_parser.add_argument('--a_option')

B_parser = subparsers.add_parser('B')
B_parser.add_argument('--b_option')

Now you can call

args = parser.parse_args(['--input', 'foo'])

but also

args = parser.parse_args(['--input', 'bar', 'A', '--a_option', 'a_option_arg'])

and

args = parser.parse_args(['--input', 'baz', 'B', '--b_option', 'b_option_arg'])

Update

In the comments, you ask:

Is it possible that I can also pass a unknown number of arguments for the --input option and still have the A option after that? Something like: program.py --input ./ ../ ../../ A -a_option

If you want to pass an unknown number of arguments to the --input option you need to pass nargs='*' to the argument definition of --input. However, you cannot use tags like A and B anymore to select your subparsers, because these would be taken as further arguments to --input.

You can resort to parent parsers in that case. With parent parsers, you can merge the options of several parsers into one:

import argparse


A_parser = argparse.ArgumentParser(add_help=False)
A_parser.add_argument('--a_option')

B_parser = argparse.ArgumentParser(add_help=False)
B_parser.add_argument('--b_option')

parser = argparse.ArgumentParser("Parser", parents=[A_parser, B_parser])
parser.add_argument('--input', nargs='*')  # this should be available for A and B

Now all options are available every time:

args = parser.parse_args(['--input', 'foo'])
args = parser.parse_args(['--input', 'foo' , 'bar', '--a_option', 'a_option_arg'])
args = parser.parse_args(['--input', 'baz', '--b_option', 'b_option_arg'])

Note that there is no more 'A' and 'B' tag. Selecting 'A' occurs by choosing one of the options defined by A_parser. It is even allowed to use both:

args = parser.parse_args(['--input', 'foo' ,'--a_option', 'a_option_arg', '--b_option', 'b_option_arg'])

If you don't want this, you would need to implement a check for conflicting parameters.

Sign up to request clarification or add additional context in comments.

2 Comments

This only works if --input is either store_true or has a defined number of arguments followd. Is it possible that the I can also pass a unknown number of arguments for the --input option and still have the A option after that? Something like: program.py --input ./ ../ ../../ A -a_option
The main parser can't tell when args for --input stop and the subparser name starts. It checks things like this by position, not value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.