Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use argparse subparsers correctly?

I've been searching through a lot of the subparser examples on here and in general but can't seem to figure this seemingly simple thing out.

I have two var types of which one has constraints so thought subparser was the way to go. e.g. -t allows for either "A" or "B". If the user passes "A" then they are further required to also specify if it is either "a1" or "a2". If they pass just "B" then nothing.

Can I do this and have argparse return me what type of "A" was passed or if it was just "B"?

The below seems to work but for some reason breaks when passing anything after the subparse.

e.g. from a linux terminal

>> python test01.py -t A a1 -v 61 

errors with...

usage: test01.py a1 [-h] test01.py a1: error: unrecognized arguments: -v 

Hopefully that makes sense.

The code:

import argparse  parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(help='types of A')  parser.add_argument("-t",                     choices = ["A", "B"],                     dest = "type",                     required=True,                     action='store',                     help="Some help blah blah")  cam_parser = subparsers.add_parser('a1', help='Default') cam_parser.set_defaults(which='a1')  cam_parser = subparsers.add_parser('a2', help='parse this instead of default') cam_parser.set_defaults(which='a2')   parser.add_argument("-v",                     nargs = '+',                     required=True,                     dest = "version",                     type=int,                     action='store',                     help="some version help blah blah")     argument = parser.parse_args()  print argument.type print argument.version 
like image 470
user1571144 Avatar asked Jun 12 '13 19:06

user1571144


People also ask

What are Subparsers in Python?

A “subparser” is an argument parser bound to a namespace. In other words, it works with everything after a certain positional argument. Argh implements commands by creating a subparser for every function.

How do you add an optional argument in Argparse?

To add an optional argument, simply omit the required parameter in add_argument() . args = parser. parse_args()if args.


1 Answers

Subparsers are invoked based on the value of the first positional argument, so your call would look like

python test01.py A a1 -v 61 

The "A" triggers the appropriate subparser, which would be defined to allow a positional argument and the -v option.

Because argparse does not otherwise impose any restrictions on the order in which arguments and options may appear, and there is no simple way to modify what arguments/options may appear once parsing has begun (something involving custom actions that modify the parser instance might work), you should consider replacing -t itself:

import argparse  parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(help='types of A') parser.add_argument("-v", ...)  a_parser = subparsers.add_parser("A") b_parser = subparsers.add_parser("B")  a_parser.add_argument("something", choices=['a1', 'a2']) 

Since -v is defined for the main parser, it must be specified before the argument that specifies which subparser is used for the remaining arguments.

like image 63
chepner Avatar answered Sep 22 '22 08:09

chepner