I have the following code (using Python 2.7):
# shared command line options, like --version or --verbose
parser_shared = argparse.ArgumentParser(add_help=False)
parser_shared.add_argument('--version', action='store_true')
# the main parser, inherits from `parser_shared`
parser = argparse.ArgumentParser(description='main', parents=[parser_shared])
# several subcommands, which can't inherit from the main parser, since
# it would expect subcommands ad infinitum
subparsers = parser.add_subparsers('db', parents=[parser_shared])
...
args = parser.parse_args()
Now I would like to be able to call this program e.g. with the --version
appended to the normal program or some subcommand:
$ prog --version
0.1
$ prog db --version
0.1
Basically, I need to declare optional subparsers. I'm aware that this isn't really supported, but are there any workarounds or alternatives?
Edit: The error message I am getting:
$ prog db --version
# works fine
$ prog --version
usage: ....
prog: error: too few arguments
As discussed in http://bugs.python.org/issue9253 (argparse: optional subparsers), as of Python 3.3, subparsers are now optional. This was an unintended result of a change in how
parse_args
checked for required arguments.I found a fudge that restores the previous (required subparsers) behavior, explicitly setting the
required
attribute of thesubparsers
action.See that issue for more details. I expect that if and when this issue gets properly patched, subparsers will be required by default, with some sort of option to set its
required
attribute toFalse
. But there is a big backlog ofargparse
patches.FWIW, I ran into this also, and ended up "solving" it by not using subparsers (I already had my own system for printing help, so didn't lose anything there).
Instead, I do this:
...and then the subcommand creates its own parser (similar to a subparser) which operates only on
subcommand_args
.According to documentation,
--version
withaction='version'
(and not withaction='store_true'
) prints automatically the version number:Yeah, I just checked
svn
, which is used as an object example in theadd_subparsers()
documentation, and it only supports '--version' on the main command:Still:
Which yields:
This seems to implement the basic idea of an optional subparser. We parse the standard arguments that apply to all subcommands. Then, if anything is left, we invoke the parser on the rest. The primary arguments are a parent of the subcommand so the -h appears correctly. I plan to enter an interactive prompt if no subcommands are present.
While we wait for this feature to be delivered, we can use code like this: