Skip to content Skip to sidebar Skip to footer

Python Argparse Creates Incorrect Usage String When Using Nested Sub-parsers

I would like to build a (complicated) command-line argument parser using argparse module facilities. The 'main' script can accept sub-commands, and some of the sub-commands also h

Solution 1:

If I add to your first script (before the return):

print("progs: ")
print("main: ", parser.prog)
print("   p: ", p.prog)
print("   r: ", r.prog)

a run is:

1319:~/mypy$python3stack63361458_0.pyc2s2-hprogs:main:stack63361458_0.pyp:stack63361458_0.pyc2r:stack63361458_0.pyc2s2usage:stack63361458_0.pyc2s2 [-h]

optional arguments:-h,--helpshowthishelpmessageandexit

usage includes the prog. If you don't provide it, argparse derives it from sys.argv[0], and for subparsers, adds on some strings to show the subparser's name (and required main arguments). Code for that addition is in add_subparses and add_parser.

Adding similar prints to the top_parser case

1349:~/mypy$python3stack63361458_0.pyc2s2-hs2 prog:stack63361458_0.pys2top prog:stack63361458_0.pyc2 prog:stack63361458_0.pyc2usage:stack63361458_0.pys2 [-h]

optional arguments:-h,--helpshowthishelpmessageandexit

c2 gets the expected prog, but s2.prog is created without "knowledge" that it will be called by the c2 subparser. Using parents bypasses that link.

But I could supply my own prog for the sub-sub-parser:

s2 = q.add_parser("s2", help="Command 1 - Sub-command 2", prog=f'MyProg {sys.argv[0]} c2 s2 ')

1358:~/mypy$ python3 stack63361458_0.py c2 s2 -h
s2 prog:  MyProg stack63361458_0.py c2 s2 
top prog:  stack63361458_0.py
c2 prog:  stack63361458_0.py c2
usage: MyProg stack63361458_0.py c2 s2  [-h]

optional arguments:
  -h, --help  show this help message and exit

We can also supply a custom usage.

Instead of the parents mechanism which creates s2 before c2, we could create c2 and then pass that to the function that creates its arguments:

defc2_parser(q):
    r = q.add_parser("s1", help="Command 1 - Sub-command 1")
    r.add_argument("arg1", help="first argument")
    r.add_argument("-a", "--arg2", help="second argument")

    r = q.add_parser("s2", help="Command 1 - Sub-command 2")

and in main:

    p = subparsers.add_parser("c2", help="Command 2")
    c2_parser(p)

parents are (somewhat) useful as a means of adding the same arguments to multiple subparsers, but aren't necessary when just refactoring larger builds.

Post a Comment for "Python Argparse Creates Incorrect Usage String When Using Nested Sub-parsers"