For a program with many subcommands, I'd like to show them logically grouped in the --help output. Python argparse has a add_argument_group method, but it doesn't seem compatible with subparsers. subparsers can only be added to the top level ArgumentParser, and _SubParsersAction doesn't allow argument groups. Is there some way around this?
You can't really do it in any straightforward way, other than implementing a custom HelpFormatter.
You can find some more information on HelpFormatter flavors in this part of the documentation.
Related
I define an argsparse object like this:
parser = argparse.ArgumentParser(description='{desc}', formatter_class=argparse.ArgumentDefaultsHelpFormatter)\
.format(desc=description)
Then I add arguments like this:
parser.add_argument("--config", "-c", help='config',
default='dbConf').format(dbConf=dbConfig)
Since I use these two lines in many scripts, I want to embed them into a function.
However, to my understanding the parser.add_argument() listens to the command line.
Is it possible to embed these lines into a function?
Is it possible to embed these lines into a function?
Yes. add_argument doesn't interact with the command line at all, though even if it did that would make little difference.
The one bit of argparse which interacts with the CLI input is the parse_args method, and what it does by default is access the global sys.argv attribute and process it. I wrote by default because you can also provide a list of strings as first parameter and it'll process that instead (if you click the link you'll see the official documentation does that to demonstrate various things in the examples).
So yes, you can very much have a function which creates an ArgumentParser and starts configuring it, then returns it for more configuration and ultimately, well, parsing the arguments.
I am currently building an extension to an existing library that uses argparse.ArgumentParser() to ingest cli arguments, and have added my own argparse.ArgumentParser() using parse_known_args() to parse out the arguments I want to inject before passing the remaining arguments on to the existing library's implementation. I am doing this instead of adding the arguments to the underlying library so that if the underlying library changes, everything should still work.
However, when I pass in the --help flag my implementation of argparse.ArgumentParser() grabs that flag, prints out help for my injected arguments then breaks execution so it never gets to the help message for the underlying library.
I am having trouble figuring out if there's a way to combine the help directives for both argparse.ArgumentParser() implementations (if it's even possible), or how to ignore the help flag in my implementation. My added arguments are for debug only and are not vital to display to the end user of my extended library, so if there is a way to ignore the help flag in my implementation, that would be OK, while not ideal.
I think this may be an answer to your question. add_help=False, but added to subcommands and subparsers. Python argparse - disable help for subcommands?
You need to pass parents parameter to the subsequent parsers. I've just posted an answer to a similar question here:
Argparse: is it possible to combine help texts from multiple parsers?
How would you construct a Python argparse parser to support different parameters organized by a top-level action, as well as have argparse's default help functionality distinguish between the different action/option groups?
e.g.
$ myprog.py list --verbose
Listing records:
...
$ myprog.py run --iterations=10
Running
...
$ myprog.py help
usage: myprog.py [action]
positional arguments:
action {list,run,help}
list Lists records.
run Process records.
help Show action help.
$ myprog.py help run
usage: myprog.py run [--iterations=N] [--verbose] [--skip]
optional arguments:
--iterations N Process N records.
--verbose Show extra messaging.
--skip Skip previously seen IDs.
I thought this might be supported by the parents feature, but this seems more designed to grouping option groups than separate argument actions.
here's an example I made of using parsers and subparsers with argparse to achieve something close to what you're looking for, and that's a code to access SO by CLI ;-)
I'd also advise you to have a look at docopt
You could parse the first item, make your choice, then have different argument parsers for each item. If you want to share some commands, then you can use the parents feature to share some arguments between your various commands.
parents is a convenient way of adding arguments to one or more parsers. It does not affect the parsing or the help.
add_argument_group is a way of grouping arguments in the help. It may be what you need. It does not, though, affect how the arguments are parsed. The default groupings are 'positional' and 'optional' (meaning 'uses a flag').
add_subparsers is a way of both grouping arguments and their parsing. With it you create new parsers that are invoked with simple commands. Each subparser has its own set of arguments (and own help display)
If you want to organize the help in an entirely different way, consider writing your own usage and description, and suppressing the default help lines with help=argparse.SUPPRESS.
IPython is an advanced user of argparse. It detects help in sys.argv before calling argparse, and thus bypasses the default help.
I need to get to work something like this:
./foo.py [-b option [-a]]
with argparse. I thought about using sub_parsers, but I don't know how to make it work.
The straightforward way is to simply add rules in the codes that gets your options to throw an error if -a is there and not b (and document it in the user help). You can also override the usage string using the usage keyword: http://docs.python.org/dev/library/argparse.html#usage
sub_parsers are nice, but I don't think they fit your needs. Their usecase is more like putting a lot of features in a single executable (think svn add, svn ci, svn co, etc)
I have an argument that is an internal debug flag and shouldn't be run by users who don't know what they are doing.
I realize that hiding it is in essence security by obscurity, but I'm not concerned about malice so much as incompetence.
Optparse had a SUPPRESS_HELP option, is there and argparse equivalent?
parser.add_argument('--secret', help=argparse.SUPPRESS)
From here: http://argparse.googlecode.com/svn/trunk/doc/argparse-vs-optparse.html
First Google result for argparse suppress_help, by the way.