1

I'm facing a problem in my python program, I have two optional arguments, the problem is that there must be at least one of these two arguments that must be used but the two arguments can't be passed together, is there a way of doing this with argparse ?

Here is the code I'm currently using:

parser = argparse.ArgumentParser(description='worker')
arser.add_argument('-i', "--item", type=bool, default=False, required=False)
parser.add_argument('-o', "--offer", type=bool, default=False, required=False)

Here are some examples of how I would like it to work:

  • ./main.py -i True => OK

  • ./main.py -o True => OK

  • ./main.py -o True -i True => Not OK

2
  • 1
    I don't know much about argparse, but this "mutual exclusion" method sounds like it would be useful. Commented Sep 26, 2014 at 14:07
  • Whenever you have "optional" arguments from which you must choose one, think "subparsers": main.py item, main.py offer. Commented Sep 26, 2014 at 14:20

2 Answers 2

7

I would suggest, you refactor the arguments and combine -o and -i into one mandatory argument. Then you define o and i (or whatever is appropriate) as allowed values using the choices argument of add_argument.

E.g:

   parser.add_argument('foo', choices=['i', 'o'])

Now the user has to specify one of the two, but can't specify both at the same time.

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

1 Comment

You don't need the required=True; positional arguments are always required (well, as long as you don't set nargs='?', anyway).
5

A mutually_exclusive_group will give you the required, but not both action.

But first, you don't want type=bool. bool is a function that converts its input to True or False, but does not convert the string 'False' to boolean False. I'd suggest using the action='store_true' instead.

In [1]: import argparse
In [2]: parser=argparse.ArgumentParser()
In [3]: g = parser.add_mutually_exclusive_group(required=True)
In [4]: g.add_argument('-i', '--item', action='store_true')
In [5]: g.add_argument('-o', '--offer', action='store_true')

In [6]: parser.parse_args('-i'.split())
Out[6]: Namespace(item=True, offer=False)

In [7]: parser.parse_args('-o'.split())
Out[7]: Namespace(item=False, offer=True)

In [8]: parser.parse_args('-o -i'.split())
usage: ipython [-h] (-i | -o)
ipython: error: argument -i/--item: not allowed with argument -o/--offer

In [11]: parser.parse_args(''.split())
usage: ipython [-h] (-i | -o)
ipython: error: one of the arguments -i/--item -o/--offer is required

It raises an error is neither of -i or -o is used, or if both. It sets the appropriate attribute to True if one or the other is used. Note that the usage line indicates this 'exclusive or' logic with (-i | -o).

Comments

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.