Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python argparser for multiple arguments for partial choices

I create a argparser like this:

  parser = argparse.ArgumentParser(description='someDesc')
  parser.add_argument(-a,required=true,choices=[x,y,z])
  parser.add_argument( ... )

However, only for choice "x" and not for choices "y,z", I want to have an additional REQUIRED argument. For eg.

python test -a x       // not fine...needs additional MANDATORY argument b
python test -a y       // fine...will run
python test -a z       // fine...will run  
python test -a x -b "ccc"       // fine...will run 

How can I accomplish that with ArgumentParser? I know its possible with bash optparser

like image 317
GJain Avatar asked Jul 29 '13 06:07

GJain


2 Answers

To elaborate on the subparser approach:

sp = parser.add_subparsers(dest='a')
x = sp.add_parser('x')
y=sp.add_parser('y')
z=sp.add_parser('z')
x.add_argument('-b', required=True)
  • this differs from your specification in that no -a is required.
  • dest='a' argument ensures that there is an 'a' attribute in the namespace.
  • normally an optional like '-b' is not required. Subparser 'x' could also take a required positional.

If you must use a -a optional, a two step parsing might work

p1 = argparse.ArgumentParser()
p1.add_argument('-a',choices=['x','y','z'])
p2 = argparse.ArgumentParser()
p2.add_argument('-b',required=True)
ns, rest = p1.parse_known_args()
if ns.a == 'x':
    p2.parse_args(rest, ns)

A third approach is to do your own test after the fact. You could still use the argparse error mechanism

parser.error('-b required with -a x')
like image 155
hpaulj Avatar answered Nov 14 '22 01:11

hpaulj


ArgumentParser supports the creation of such sub-commands with the add_subparsers() method. The add_subparsers() method is normally called with no arguments and returns a special action object. This object has a single method, add_parser(), which takes a command name and any ArgumentParser constructor arguments, and returns an ArgumentParser object that can be modified as usual.

ArgumentParser.add_subparsers()
like image 42
Udy Avatar answered Nov 14 '22 03:11

Udy