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.
Related
There is a ready-made program that works with pytest, an ordinary user will work with it and for him and his colleagues it is necessary to create a help that would be called using --help, but this argument calls the pytest help and the necessary information about the added arguments used is at the very beginning of the end, which is not very convenient.
Is it possible to change the received help using the --help argument (you need to describe your functions and how to work with them)?
I have two parameters that I need either both or neither of. I thought of two solutions: one optional parameter with nargs=2, or two optional parameters that are contingent on each other. I found answers for nargs=2, but the help output seems messy and opaque to users. I'd like to investigate making two optional parameters that are contingent on each other.
If I provide the environment, I also need to provide the service, and vice-versa. If I provide neither, that's fine.
Normal optional parameters get added with this type of help output:
usage: script.py [-h] [-e ENVIRONMENT] [-s SERVICE] [-u] [-d]
I want this type of help output (and the underlying requirements):
usage: script.py [-h] [-e ENVIRONMENT -s SERVICE] [-u] [-d]
Is there a flag or easy way to do this, so it shows up clearly in the help? Writing an additional check to enforce this is trivial, but making my help clear to users seems out of my reach.
In the mean time, I've added help to the argparse like this: parser.add_argument('-s', '--service', metavar='SERVICE', help='Service to use, if -e also used')
Though this option is not currently supported in argparse, you can use subparser as a workaround solution.
Each dependent parameter will define a new subparser which will contain the other parameter as a required parameter.
It's a bit ugly and will create some code duplication, but it will solve your dependency problem and also will be reflected properly in the help and error.
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?
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.
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)