Argparse: Required argument 'y' if 'x' is present
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Puzzle Game 3
--
Chapters
00:00 Argparse: Required Argument 'Y' If 'X' Is Present
00:36 Accepted Answer Score 192
01:00 Answer 2 Score 87
01:39 Answer 3 Score 21
02:44 Answer 4 Score 10
03:08 Answer 5 Score 2
03:50 Thank you
--
Full question
https://stackoverflow.com/questions/1941...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #argparse
#avk47
ACCEPTED ANSWER
Score 193
No, there isn't any option in argparse to make mutually inclusive sets of options.
The simplest way to deal with this would be:
if args.prox and (args.lport is None or args.rport is None):
    parser.error("--prox requires --lport and --rport.")
Actually there's already an open PR with an enhancement proposal : https://github.com/python/cpython/issues/55797
ANSWER 2
Score 89
You're talking about having conditionally required arguments. Like @borntyping said you could check for the error and do parser.error(), or you could just apply a requirement related to --prox when you add a new argument.
A simple solution for your example could be:
non_int.add_argument('--prox', action='store_true', help='Flag to turn on proxy')
non_int.add_argument('--lport', required='--prox' in sys.argv, type=int)
non_int.add_argument('--rport', required='--prox' in sys.argv, type=int)
This way required receives either True or False depending on whether the user as used --prox. This also guarantees that -lport and -rport have an independent behavior between each other.
ANSWER 3
Score 21
How about using parser.parse_known_args() method and then adding the --lport and --rport args as required args if --prox is present.
# just add --prox arg now
non_int = argparse.ArgumentParser(description="stackoverflow question", 
                                  usage="%(prog)s [-h] [--prox --lport port --rport port]")
non_int.add_argument('--prox', action='store_true', 
                     help='Flag to turn on proxy, requires additional args lport and rport')
opts, rem_args = non_int.parse_known_args()
if opts.prox:
    non_int.add_argument('--lport', required=True, type=int, help='Listen Port.')
    non_int.add_argument('--rport', required=True, type=int, help='Proxy port.')
    # use options and namespace from first parsing
    non_int.parse_args(rem_args, namespace = opts)
Also keep in mind that you can supply the namespace opts generated after the first parsing while parsing the remaining arguments the second time. That way, in the the end, after all the parsing is done, you'll have a single namespace with all the options. 
Drawbacks:
- If 
--proxis not present the other two dependent options aren't even present in the namespace. Although based on your use-case, if--proxis not present, what happens to the other options is irrelevant. - Need to modify usage message as parser doesn't know full structure
 --lportand--rportdon't show up in help message
ANSWER 4
Score 10
Do you use lport when prox is not set.  If not, why not make lport and rport arguments of prox?  e.g.
parser.add_argument('--prox', nargs=2, type=int, help='Prox: listen and proxy ports')
That saves your users typing.  It is just as easy to test if args.prox is not None: as if args.prox:.