4

I have been trying to set up a main parser with two subs parser so that when called alone, the main parser would display a help message.

def help_message():
    print "help message"

import argparse
parser = argparse.ArgumentParser()

subparsers = parser.add_subparsers(dest='sp')

parser_a = subparsers.add_parser('a')
parser_a.required = False
#some options...
parser_b = subparsers.add_parser('b')
parser_b.required = False
#some options....

args = parser.parse_args([])

if args.sp is None:
    help_message()
elif args.sp == 'a':
    print "a"
elif args.sp == 'b':
    print "b"

This code works well on Python 3 and I would like it to work aswell on Python 2.x

I am getting this when running 'python myprogram.py'

myprogram.py: error: too few arguments

Here is my question : How can i manage to write 'python myprogram.py' in shell and get the help message instead of the error.

Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
Lucas
  • 65
  • 1
  • 6
  • What might the question be? – Tim Jun 13 '14 at 14:32
  • 1
    I've never seen sub parsers marked as optional, and I don't see anything in the docs to suggest this is supported. Given that you would get a help message if you omitted the required subcommand, I'm not sure I see why it is useful to allow an optional subcommand. – chepner Jun 13 '14 at 14:34
  • You're also duplicating a lot of functionality that is already built into ``argparse``. It already has all the facilities for displaying help messages when required arguments are left out. – aruisdante Jun 13 '14 at 14:35
  • Well the message I want to display is to present the whole functionnalities to a newcomer, this program will be used by non-informatics-oriented people so they will type the program name. I want them to have a full program explanation by doing this instead of expecting them to type 'python myprogram -h' then 'python myprogram a -h' and 'python myprogram b -h'. Thing is that Python 3 will run the function help_message() and Python 2 will display an error and i'd like to overcome it. – Lucas Jun 13 '14 at 14:42

2 Answers2

6

I think you are dealing the bug discussed in http://bugs.python.org/issue9253

Your subparsers is a positional argument. That kind of argument is always required, unless nargs='?' (or *). I think that is why you are getting the error message in 2.7.

But in the latest py 3 release, the method of testing for required arguments was changed, and subparsers fell through the cracks. Now they are optional (not-required). There's a suggested patch/fudge to make argparse behave as it did before (require a subparser entry). I expect that eventually py3 argparse will revert to the py2 practice (with a possible option of accepting a required=False parameter).

So instead of testing args.sp is None, you may want to test sys.argv[1:] before calling parse_args. Ipython does this to produce it's own help message.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • Thanks for your answer, I did not consider not calling parse_args() immediately. I added a new argparse.Namespace object and i overcome the problem with that and the sys.argv[1:] as you said. If anyone wants to do the same check this [url](http://stackoverflow.com/questions/16878315/what-is-the-right-way-to-treat-python-argparse-namespace-as-a-dictionary) – Lucas Jun 16 '14 at 12:03
  • BOOM! Solution also applies to the Java version, argparse4j, just add .nargs("?") to subcommand parameters – Darek Feb 11 '19 at 18:03
0

For others - I ended up on this page while trying to figure out why I couldn't just call my script with no arguments while using argparse in general.

The tutorial demonstrates that the difference between an optional argument and a required argument is adding "--" to the name:

parser.add_argument("--show")  <--- Optional arg
parser.add_argument("show")    <--- Not optional arg
Locane
  • 2,886
  • 2
  • 24
  • 35