29

Currently I'm creating a directory reader program using Python. I'm using 'argparse' to parse the arguments from command line. I have the following code:

parser = argparse.ArgumentParser(prog = "LS.py", usage = "%(prog)s [options] [path1 [path2 [...pathN]]]\nThe paths are optional; if not given . is used.") group = parser.add_argument_group("Options") group.add_argument("-path", default = ".", help = argparse.SUPPRESS, metavar = "") group.add_argument("-m", "--modified", default = False, help = "show last modified date/time [default: off]", metavar = "") group.add_argument("-o ORDER", "--order=ORDER", nargs = 2, default = "name", help = "order by ('name', 'n', 'modified', 'm', 'size', 's')\n[default: name]", metavar = "") group.add_argument("-r", "--recursive", default = False, help = "recurse into subdirectories [default: off]", metavar = "") group.add_argument("-s", "--sizes", default = False, help = "show sizes [default: off]", metavar = "") args = parser.parse_args() return args 

When called in the following manner "LS.py -h" it produces the following output:

usage: LS.py [options] [path1 [path2 [...pathN]]] The paths are optional; if not given . is used. optional arguments: -h, --help show this help message and exit Options: -m , --modified show last modified date/time [default: off] -o ORDER , --order=ORDER order by ('name', 'n', 'modified', 'm', 'size', 's') [default: name] -r , --recursive recurse into subdirectories [default: off] -s , --sizes show sizes [default: off] 

My question: Is there a way to move the default help argument into a group such as Options? Also, I can't seem to find a way to remove the space before the commas in the Options arguments. The ideal output is:

Usage: ls.py [options] [path1 [path2 [...pathN]]] The paths are optional; if not given . is used. Options: -h, --help show this help message and exit -m, --modified show last modified date/time [default: off] -o ORDER, --order=ORDER order by ('name', 'n', 'modified', 'm', 'size', 's') [default: name] -r, --recursive recurse into subdirectories [default: off] -s, --sizes show sizes [default: off] 

4 Answers 4

35

You can use add_help=False to disable the built-in help command and add your own instead, using action="help" (thanks @mgilson!)

To get rid of the spaces, don't set metavar to an empty string. Your options should be specified using action="store_true" to make them true (argument-less) options:

import argparse parser = argparse.ArgumentParser(prog="LS.py", usage="%(prog)s [options] [paths...]\nThe paths are optional; if not given . is used.", add_help=False) group = parser.add_argument_group("Options") group.add_argument("-h", "--help", action="help", help="show this help message and exit") group.add_argument("-path", default=".", help=argparse.SUPPRESS) group.add_argument("-m", "--modified", action="store_true", help="show last modified date/time") group.add_argument("-o", "--order", nargs=1, default="name", help="sort order (n[ame], m[odified], s[ize])\n[default: name]") group.add_argument("-r", "--recursive", action="store_true", help="recurse into subdirectories") group.add_argument("-s", "--sizes", action="store_true", help="show sizes") args = parser.parse_args() 

Output:

Options: -h, --help show this help message and exit -m, --modified show last modified date/time -o ORDER, --order ORDER sort order (n[ame], m[odified], s[ize]) [default: name] -r, --recursive recurse into subdirectories -s, --sizes show sizes 
Sign up to request clarification or add additional context in comments.

3 Comments

It's even easier if you use action = "help" instead of action="store_true"
Derp, I must've missed it while skimming the action docs. Thanks!
This answered all of my questions, thank you very much. I had been looking through the documentation for a while and couldn't seem to find it.
8

Sure you can do that. The trick is to just add add_help=False the the ArgumentParser constructor and then add your own help action to the group:

import argparse parser = argparse.ArgumentParser(prog = "LS.py", usage = "%(prog)s [options] [path1 [path2 [...pathN]]]\nThe paths are optional; if not given . is used.", add_help=False) group = parser.add_argument_group("Options") group.add_argument("-path", default = ".", help = argparse.SUPPRESS, metavar = "") group.add_argument("-m", "--modified", default = False, help = "show last modified date/time [default: off]", metavar = "") group.add_argument("-o ORDER", "--order=ORDER", nargs = 2, default = "name", help = "order by ('name', 'n', 'modified', 'm', 'size', 's')\n[default: name]", metavar = "") group.add_argument("-h", "--help", action='help', help='print this fabulous help message') group.add_argument("-r", "--recursive", default = False, help = "recurse into subdirectories [default: off]", metavar = "") group.add_argument("-s", "--sizes", default = False, help = "show sizes [default: off]", metavar = "") args = parser.parse_args() 

Comments

1

To condense and simplify a bit upon the previous answer by nneonneo, you can have:

import argparse parser = argparse.ArgumentParser(prog="LS.py", usage="%(prog)s [options] [paths...]\nThe paths are optional; if not given . is used.", add_help=False) add_arg = parser.add_argument_group("Options").add_argument add_arg("-h", "--help", action="help", help="show this help message and exit") add_arg("-path", default=".", help=argparse.SUPPRESS) add_arg("-m", "--modified", action="store_true", help="show last modified date/time") add_arg("-o", "--order", nargs=1, default="name", help="sort order (n[ame], m[odified], s[ize])\n[default: name]") add_arg("-r", "--recursive", action="store_true", help="recurse into subdirectories") add_arg("-s", "--sizes", action="store_true", help="show sizes") args = parser.parse_args() 

Basically, the slight variation from the previous answer is that it is not necessary to save group and then repeatedly call the the add_argument method on it.

Comments

0

In my case, I'm working in a module of a larger application that creates the ArgumentParser object for me so setting add_help=False isn't an option. I can set that variable on the ArgumentParser object but that doesn't do any good; the help argument has already been created. Instead, I did this (horrible, unsupported hack) to move it from the default "optional arguments" group into my own "Other arguments" group:

if '_action_groups' in parser.__dict__ \ and 4 == len(parser._action_groups) \ and 'optional arguments' == parser._action_groups[1].title \ and 'Other arguments' == parser._action_groups[3].title \ and '_group_actions' in parser._action_groups[1].__dict__: act = next((x for x in parser._action_groups[1]._group_actions if 'help' == x.dest), None) if None != act: parser._action_groups[1]._group_actions.remove(act) parser._action_groups[3]._group_actions.append(act) 

Any and all of that may break in the next release of Python, but hopefully all of my checks will prevent any such changes from crashing the program and just make "--help" in the default "optional arguments" group.

A better version of this would search for the "optional arguments" and "Other arguments" groups rather than assuming that they're at indices 0 and 3.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.