I am implementing a command line program which has interface like this:
cmd [GLOBAL_OPTIONS] {command [COMMAND_OPTS]} [{command [COMMAND_OPTS]} ...]
I have gone through the argparse documentation. I can implement GLOBAL_OPTIONS
as optional argument using add_argument
in argparse
. And the {command [COMMAND_OPTS]}
using Sub-commands.
From the documentation it seems I can have only one sub-command. But as you can see I have to implement one or more sub-commands. What is the best way to parse such command line arguments useing argparse
?
Improving on the answer by @mgilson, I wrote a small parsing method which splits argv into parts and puts values of arguments of commands into hierarchy of namespaces:
It behaves properly, providing nice argparse help:
For
./test.py --help
:For
./test.py cmd1 --help
:And creates a hierarchy of namespaces containing the argument values:
I came up with the same qustion, and it seems i have got a better answer.
The solution is we shall not simply nest subparser with another subparser, but we can add subparser following with a parser following another subparser.
Code tell you how:
Another package which supports parallel parsers is "declarative_parser".
and namespace becomes:
Disclaimer: I am the author. Requires Python 3.6. To install use:
Here is the documentation and here is the repo on GitHub.
parse_known_args
returns a Namespace and a list of unknown strings. This is similar to theextra
in the checked answer.produces:
An alternative loop would give each subparser its own namespace. This allows overlap in positionals names.
@mgilson has a nice answer to this question. But problem with splitting sys.argv myself is that i lose all the nice help message Argparse generates for the user. So i ended up doing this:
Now after first parse all chained commands are stored in
extra
. I reparse it while it is not empty to get all the chained commands and create separate namespaces for them. And i get nicer usage string that argparse generates.you can use the package optparse