Skip to content

argparse subparser usage message hides main parser usage #64532

Description

@MartindAnjou
BPO 20333
Files
  • issue20333.patch
  • sample.py
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2014-01-21.16:46:08.797>
    labels = ['type-feature', 'library']
    title = 'argparse subparser usage message hides main parser usage'
    updated_at = <Date 2014-05-09.21:27:37.768>
    user = 'https://bugs.python.org/MartindAnjou'

    bugs.python.org fields:

    activity = <Date 2014-05-09.21:27:37.768>
    actor = 'paul.j3'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Library (Lib)']
    creation = <Date 2014-01-21.16:46:08.797>
    creator = "Martin.d'Anjou"
    dependencies = []
    files = ['35203', '35204']
    hgrepos = []
    issue_num = 20333
    keywords = ['patch']
    message_count = 2.0
    messages = ['208670', '218199']
    nosy_count = 3.0
    nosy_names = ['bethard', 'paul.j3', "Martin.d'Anjou"]
    pr_nums = []
    priority = 'normal'
    resolution = None
    stage = None
    status = 'open'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue20333'
    versions = ['Python 3.3']

    Linked PRs

    Activity

    1. MartindAnjou commented on Jan 21, 2014

      MartindAnjoumannequin
      MannequinAuthor

      Consider the following code:

      #!/usr/bin/env python3
      import argparse
      
      # create the top-level parser
      parser = argparse.ArgumentParser(prog='PROG')
      parser.add_argument('--file', help='A filename', required=True)
      subparsers = parser.add_subparsers(help='sub-command help')
      
      # create the parser for the "a" command
      parser_a = subparsers.add_parser('a', help='a help')
      parser_a.add_argument('bar', type=int, help='bar help')
      
      # create the parser for the "b" command
      parser_b = subparsers.add_parser('b', help='b help')
      parser_b.add_argument('--baz', choices='XYZ', help='baz help')

      The help for subparser a is obtained with: parser.parse_args(["a","--help"])

      usage: PROG a [-h] bar
      
      positional arguments:
        bar         bar help
      
      optional arguments:
        -h, --help  show this help message and exit
      

      When the user follows the help, the user gets it wrong:
      parser.parse_args(["a","10"])

      usage: PROG [-h] --file FILE {a,b} ...
      PROG: error: argument --file is required
      

      The correct way to use the subparser is:
      parser.parse_args(["--file","file","a","10"])

      But the problem is that the original help message is not telling the user that this is the correct way. When asking for the "a" subparser help, the usage message should also reveal the main parser arguments. Continuing with the example, something like this should be appropriate:

      usage: PROG [-h] --file FILE a [-h] bar
      

      This is how the argparse Java port works.

    2. added
      stdlibStandard Library Python modules in the Lib/ directory
      type-featureA feature request or enhancement
      on Jan 21, 2014
    3. paulj3 commented on May 9, 2014

      paulj3mannequin
      Mannequin

      When add_subparsers creates the _prog_prefix it uses a list of positionals. That makes sense, since a subparser argument is positional, so the user needs to know where it fits in the broader scope of positionals.

      But it intentionally skips the 'optionals'. The problem in the example for this bug is that its 'optional' is 'required'. A fix is to include all 'required optionals' along with positionals in the usage prefix.

      Attached is a partial patch that does this.

      I also question whether it makes sense to include 'mutually_exclusive_groups' in this usage formatting, since all actions in such a group must be non-required. And such a group can include at most one positional (with ? or *). A MXG is marked only if all of its actions are present in the usage list.

      The programmer can also customize the subparsers usage with the 'prog' keyword of either the 'add_subparsers' or 'add_parser' commands. I illustrate this in the attached 'sample.py' script.

      'test_argparse.py' does not seem to test this issue much. Atleast it isn't bothered by these tweaks.

      Note that any arguments added to the main parser after the 'add_subparsers' command will not appear the subparser usage, since this is defined when the subparsers are created.

    4. transferred this issue fromon Apr 10, 2022
    5. added a commit that references this issue on Dec 6, 2025
    6. moved this from Features to Doc issues in Argparse issueson Dec 6, 2025
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions