Group in a group ArgParse

The mutually exclusive group mechanism is just for a simple (flat) exclusive or group. There's no mechanism for nesting one group in another, or for applying other logic (and, any etc).

You need to do your own testing after parsing. As long as the defaults are reasonable (e.g. the default default None) that isn't hard.

Subparsers provide another kind of grouping logic, which may work for you.

This has been raised in other SO questions, and a Python bug/issue, if you need to explore it in more detail.

===============

argument groups, despite the name, do not work with mutually exclusive groups. Their intended purpose is entirely different (grouping of help lines). You can nest one mutually exclusive group within another, but the net effect is to put everything in one group.

argparse: some mutually exclusive arguments in required group

============================

import argparse

usage = '%(prog)s [A | [B ? C]]'
parser = argparse.ArgumentParser(usage=usage)
parser.add_argument('-a')
parser.add_argument('-b')
parser.add_argument('-c')
args=parser.parse_args()

print(args)
if args.a is not None:
   if not(args.b is None and args.c is None):
      parser.error('Cannot use b or c with a')

with resulting runs

1722:~/mypy$ python3 stack37311550.py -a 1
Namespace(a='1', b=None, c=None)
1726:~/mypy$ python3 stack37311550.py -a 1 -b2
Namespace(a='1', b='2', c=None)
usage: stack37311550.py [A | [B ? C]]
stack37311550.py: error: Cannot use b or c with a
1726:~/mypy$ python3 stack37311550.py -c3 -b2
Namespace(a=None, b='2', c='3')
1726:~/mypy$ python3 stack37311550.py -c3 -b2 -a1
Namespace(a='1', b='2', c='3')
usage: stack37311550.py [A | [B ? C]]
stack37311550.py: error: Cannot use b or c with a

import argparse

parser = argparse.ArgumentParser(description='test group')
subparsers = parser.add_subparsers(help='sub-commands help')
sp = subparsers.add_parser('A', help='A command')
sp.set_defaults(cmd = 'A')
sp = subparsers.add_parser('B', help='B command')
sp.set_defaults(cmd = 'B')
sp.add_argument('C', help='C option')

args = parser.parse_args()

if (args.cmd == 'A'):
    print("running A mode")
else:
    print("running B mode with C=%s" % args.C)

Here's execution log:

$ python test.py A
running A mode
$ python test.py B
usage: test.py B [-h] C
$ python test.py B some
running B mode with C=some

Mutually exclusive groups are intended for cases when user have to select at least one option out of a given set, or if required=True exactly one option.