Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

argparse with required subcommands

With python's argparse, how do I make a subcommand a required argument? I want to do this because I want argparse to error out if a subcommand is not specified. I override the error method to print help instead. I have 3-deep nested subcommands, so it's not a matter of simply handling zero arguments at the top level.

In the following example, if this is called like so, I get:

$./simple.py $ 

What I want it to do instead is for argparse to complain that the required subcommand was not specified:

import argparse  class MyArgumentParser(argparse.ArgumentParser):     def error(self, message):         self.print_help(sys.stderr)         self.exit(0, '%s: error: %s\n' % (self.prog, message))  def main():     parser = MyArgumentParser(description='Simple example')     subs = parser.add_subparsers()     sub_one = subs.add_parser('one', help='does something')     sub_two = subs.add_parser('two', help='does something else')      parser.parse_args()  if __name__ == '__main__':     main() 
like image 374
PonyEars Avatar asked Aug 16 '13 21:08

PonyEars


People also ask

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.

What does parse_args return?

Adding arguments Later, calling parse_args() will return an object with two attributes, integers and accumulate . The integers attribute will be a list of one or more ints, and the accumulate attribute will be either the sum() function, if --sum was specified at the command line, or the max() function if it was not.

What is a Subparser?

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.


2 Answers

There was a change in 3.3 in the error message for required arguments, and subcommands got lost in the dust.

http://bugs.python.org/issue9253#msg186387

There I suggest this work around, setting the required attribute after the subparsers is defined.

parser = ArgumentParser(prog='test') subparsers = parser.add_subparsers() subparsers.required = True subparsers.dest = 'command' subparser = subparsers.add_parser("foo", help="run foo") parser.parse_args() 

update

A related pull-request: https://github.com/python/cpython/pull/3027

like image 194
hpaulj Avatar answered Sep 20 '22 16:09

hpaulj


In addition to hpaulj's answer: you can also use the required keyword argument with ArgumentParser.add_subparsers() since Python 3.7. You also need to pass dest as argument. Otherwise you will get an error: TypeError: sequence item 0: expected str instance, NoneType found.

Example file example.py:

import argparse  parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(dest='command', required=True) foo_parser = subparsers.add_parser("foo", help="command foo") args = parser.parse_args() 

Output of the call without an argument:

$ python example.py usage: example.py [-h] {foo} ... example.py: error: the following arguments are required: command 
like image 29
Henrik Avatar answered Sep 20 '22 16:09

Henrik