optimcode
optimcode

Reputation: 342

parsing argument in python

I have a problem I am trying to find a solution. I am not sure if I can do it with argparse.

I want to be able to specify an option

myprog -a 1
myprog -a 2

Now when I have a = 1, I want to be able to specify b and c. But when a = 2, I can only specify d.

myprog -a 1 -b 3 -c 0
myprog -a 2 -d 3

Also a must always be specified

Upvotes: 1

Views: 556

Answers (2)

ShadowRanger
ShadowRanger

Reputation: 155323

You can't do this with switched values as a single parse_args call, but you can do one of:

  1. Use sub-commands/sub-parsers
  2. Do partial parsing before fully configuring the parser and running on the complete command line, at first only checking for a, and then selecting the additional parser args to parse based on the result of the first call. The trick is to use parse_known_args for the first call, so it handles a (which it recognizes) and ignores everything else.

For example, for approach #2, you could do:

parser = argparse.ArgumentParser()
parser.add_argument('-a', required=True, type=int, choices=(1, 2)
args = parser.parse_known_args()

if args.a == 1:
    parser.add_argument('-b', ...)
    parser.add_argument('-c', ...)    
    args = parser.parse_args()
else:
    parser.add_argument('-d', ...)
    args = parser.parse_args()

Downside to this approach is that the usage info spat out for incorrect usage will be incomplete; you'd have to include the text specifying the "real" usage in the base parser manually, which is no fun. Subparsers can't be toggled based on value switches, but they have a unified, coherent usage display.

Upvotes: 1

hpaulj
hpaulj

Reputation: 231335

The simplest solution is to make '-a' a required=True argument, and leave the others with default not-required. Then after parsing perform the tests on a args.a and the other values (I assume you can write that kind of Python logic).

You can raise your own errors, or you can use a parser.error("I don't like your input") call.

You many need to write a custom usage line. What would be a meaningful usage, given these requirements?

There is a mutually exclusive argument group method, but it does not use specific values, just the presence or not of arguments.

You could also incorporate the tests in custom Action classes. But usually that's more complicated than performing the tests after parsing (since argparse handles arguments that occur in any order).

Another possibility to convert the -a argument into a subparser. That allows you to define one set of arguments for one 'parser' value, and another set for another value. I think the argparse documentation is clear enough on that.

Upvotes: 1

Related Questions