polka polka - 7 months ago 12
Python Question

How should I structure the argparse to form this?

How should I structure the argparse to form this? You should be able to call -l,-m,-s,-h,home or work but not both. You should have to call -l or -m before you can use any -i.

usage: prog
(-l | -m ) [-i1][-i2][-i3][-i4]
-s
-h
home
work


can be called using:

prog home
prog work
prog -l -i1
prog -m -i1 -i2
prog -s


The code that I wrote to make something like it.

def get_args():
parser = argparse.ArgumentParser(prog="prog")
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-l', action='store_true', help='List Mode. List available options', default=False, dest='list')
group.add_argument('-m', action='store_true', help='Departure Mode. Return a departure time from stopcode or agency and stopname', default=False, dest='mode')
group.add_argument('-s', action='store_true', help='Setup Mode. Enter setup mode to make a home and a work list of station codes.', default=False, dest='setup')
group.add_argument('home', help='Display HOME_LIST') # this causes it to break because positional arguments cant be required for some reason
group.add_argument('work', help='Display WORK_LIST')
parser.add_argument('-i1', nargs='?', dest='i1')
parser.add_argument('-i2', nargs='?', dest='i1')
parser.add_argument('-i3', nargs='?', dest='i1')
return parser.parse_args()

Answer

I'll clean this up a bit:

parser = argparse.ArgumentParser(prog="prog")

group = parser.add_mutually_exclusive_group(required=True)

one, and only one, of the following is allowed and required

group.add_argument('-l', '--list', action='store_true', 
    help='List Mode. List available options')

for 'store_true' default is False; no need to define it. Give the 'dest' in the long name

group.add_argument('-m', '--mode', action='store_true',
   help='Departure Mode. Return a departure time from stopcode or agency and stopname')

group.add_argument('-s', '--setup', action='store_true', 
   help='Setup Mode. Enter setup mode to make a home and a work list of station codes.')

group.add_argument('home',nargs='?', default='unknown',  help='Display HOME_LIST') 

Positional arguments are required by nature (unless nargs='?'). So they don't fit in a mutually_required_group. How can you supply one of the other arguments and still supply this required positional?

Only one optional positional is allowed in a m_ex_group.

parser.add_argument('work', help='Display WORK_LIST')

Why the nargs='?'? By nature they are optional. So they'll get the default value if not given. '?' is useful if you also define a const.

parser.add_argument('--i1')
parser.add_argument('--i2')
parser.add_argument('--i3')

return parser.parse_args()

You can specify the relative order of positionals. In this case work will come after home. But optionals can occur in any order. So these --i* arguments can occur anywhere. But that shouldn't matter.

To require -l or -m along with --i1 (etc), will require subparsers. That is, you'll define something like

sp = parser.add_subparsers(dest='mode')
p0 = sp.add_parser('list')
p1 = sp.add_parser('mode')
p2 = sp.add_parser('setup')

p0.add_argument('--i1')
p0.add_argument('--i2')
...
p1.add_argument('--i1')
...

But subparsers don't play nicely with other positionals, especially '?' ones.

e.g. argparse optional positional argument and subparsers arguments

Comments