Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

argparse: some mutually exclusive arguments in required group

I have a set of arguments that can logically be separated in 2 groups:

  • Actions: A1, A2, A3, etc.
  • Informations: I1, I2, I3, etc.

At least one of these arguments is required for the program to start, but "information" args can be used with "action" args. So

  • At least one in Actions or Informations is required
  • All Actions are mutually exclusive

I can't find how to do it using argparse. I know about add_mutually_exclusive_group and its required argument, but I can't use it on "Actions" because it's not actually required. Of course, I could add a condition after argparse to manually check my rules, but it seems like an hack. Can argparse do this?

Edit: Sorry, here are some examples.

# Should pass
--A1
--I1
--A1 --I2
--A2 --I1 --I2

# Shouldn't pass
--A1 --A2
--A1 --A2 --I1
like image 333
Nil Avatar asked Feb 12 '16 18:02

Nil


People also ask

What does Nargs do in Argparse?

Using the nargs parameter in add_argument() , you can specify the number (or arbitrary number) of inputs the argument should expect. In this example named sum.py , the --value argument takes in 3 integers and will print the sum.

What does Argparse ArgumentParser ()?

The ArgumentParser.parse_args() method runs the parser and places the extracted data in a argparse.Namespace object: args = parser. parse_args() print(args.


1 Answers

There's nothing hacky about verifying arguments after they've been parsed. Just collect them all in a single set, then confirm that it is not empty and contains at most one action.

actions = {"a1", "a2", "a3"}
informations = {"i1", "i2", "i3"}
p = argparse.ArgumentParser()
# Contents of actions and informations contrived
# to make the example short. You may need a series
# of calls to add_argument to define the options and
# constants properly
for ai in actions + informations:
    p.add_argument("--" + ai, action='append_const', const=ai, dest=infoactions)

args = p.parse_args()
if not args.infoactions:
    p.error("At least one action or information required")
elif len(actions.intersection(args.infoactions)) > 1:
    p.error("At most one action allowed")
like image 154
chepner Avatar answered Oct 19 '22 05:10

chepner