0

My requirement is to achieve following with argparse:

script.py <command> (-a|--first-name [--middle-name] [--last-name])

So basically, the script would accept one mandatory parameter , which can have different values. And then another parameter which should either be -a or --first-name. Then first-name can have further parameters.

I was exploring subparsers and mutually exclusive group, but can't figure out how to achieve this

One crude way I am handling this is

parser = argparse.ArgumentParser(prog='myscript', usage='%(prog)s <command> (-a|--first-name [--middle-name] [--last-name])')
parser.add_argument('command')

mxgroup = parser.add_mutually_exclusive_group(required=True)
mxgroup.add_argument('-a', action='store_true', help='Choose all')
mxgroup.add_argument('--first-name', dest='fname')

parser.add_argument('--middle-name', dest='mname')
parser.add_argument('--last-name', dest='lname')

args = parser.parse_args()

if (args.mname or args.lname) and not args.fname:
    parser.error('middle and last names may be specified with first name only')

But I am thinking if these checks can be handled by argparse inherently then I won't have to redo it as the script grows

Any help would be much appreciated

mittal
  • 915
  • 10
  • 29
  • So you want to let the user specify `--middle-name` and `--last-name` *only* if they also specify `--first-name`? Is there any dependency between `--middle-name` and `--last-name`? Or can the user specify just first name + last name or first name + middle name? – Bakuriu Sep 09 '16 at 07:10
  • No dependency between middle and last name. But user must specify either -a or --first-name along with mandatory – mittal Sep 09 '16 at 07:12
  • Is `` a fixed string? If so you can use the `add_subparsers` and simply specif `--first-name` as a `required=True` argument for the subparser. – Bakuriu Sep 09 '16 at 07:16
  • is not fixed. It can take different values – mittal Sep 09 '16 at 07:18
  • 1
    Then that's a problem. I don't think there is any way to do this using built-in methods, you'll have to specify the arguments you need and then manually check whether the user provided the right set and if not manually print an error and show the help message. – Bakuriu Sep 09 '16 at 07:40
  • The only alternativet that I could see would be to change your syntax using subparsers, i.e. change `-a` and `--first-name` to be subparsers. and so you'd have: `script.py a ` and `script.py first-name [--middle-name] [--last-name]`. Note that `argparse` has some limitations that are enforced to avoid weird command lines, and one rule of thumb is that options should be *optional*. – Bakuriu Sep 09 '16 at 08:31
  • Yeah I thought of that too, but then -a and --first-name in my case don't qualify as separate commands so they don't deserve subparsers. I even tried add_parser('-a') for the subparsers, but calling it from command line they are still treated as -a option and not subparser command – mittal Sep 09 '16 at 08:42
  • Subparser names should **not** start with hyphens. That's why I said that you have to **change** the syntax, from `-a` and `--first-name` to `a` and `first-name`. Also: whether or not this makes sense depends on what you are dealing with, and currently you didn't provide enough information to know whether it's okay or not. – Bakuriu Sep 09 '16 at 08:50
  • That duplicate suggests what he's already doing - a post-parsing test, or an `nargs` alternative (which I repeat below). – hpaulj Sep 09 '16 at 18:52

1 Answers1

0

There's nothing crude about testing values after parsing. All the mutually exclusive group does is format the usage (which you've probably already seen), and test each argument in the group against a set of 'already-seen' actions. There's no nesting or compound logic testing, just a simple, flat, xor.

I'd suggest a ('--name', nargs='+', help='name - first [last [middle]]') kind of argument. That is, accept one or more strings for the name. The result will be a list, which you can easily parse as the 3 parts. It even lets you user specify a 4 part name, or one of those aristocratic 10 part ones.

Some of the sidebar questions explore this in more detail, for example

Python argparse mutual exclusive group

Community
  • 1
  • 1
hpaulj
  • 221,503
  • 14
  • 230
  • 353