This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Title: Argparse: main arguments and subparser arguments indistinguishable
Type: behavior Stage: test needed
Components: Library (Lib) Versions: Python 3.4
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: Ingo.Fischer, bethard, ezio.melotti, paul.j3, samwyse, tshepang
Priority: normal Keywords:

Created on 2012-07-11 11:05 by Ingo.Fischer, last changed 2022-04-11 14:57 by admin. This issue is now closed.

File name Uploaded Description Edit Ingo.Fischer, 2012-07-11 11:05 samwyse, 2012-07-14 12:05
Messages (5)
msg165248 - (view) Author: Ingo Fischer (Ingo.Fischer) Date: 2012-07-11 11:05
I have an argument called '--verbose' in the main parser. 
Then I add a subparser called 'command', to which I add an argument with the same name '--verbose' (See attached script).

When I process these args, I cannot decide afterwards if the user called 'myscript --verbose command' or 'myscript command --verbose'. I always get the same Namespace object returned from parse_args.

IMHO the Namespace object should also provide informations about the source parser, to make main parser args and subparser args distinguishable. Also if I call 'myscript --verbose command --verbose', I should get both args in the resulting Namespace object.
msg165441 - (view) Author: Samwyse (samwyse) * Date: 2012-07-14 12:05
The Namespace object contains a combined list of all of the arguments, from both the main parser and the subparser.  I don't see any way to resolve identically name augments without breaking a lot of code that relies on the current behavior.  I would instead propose that anyone needing to distinguish between identically named args in nested parsers use distinct names as the primary name of the argument, and the non-distictive name as an alias.  For example:
    parser.add_argument('--verbose(main)', '--verbose', ...)

Running the attached file produces the following output.

# using non-distinctive args
['--verbose', 'command'] => Namespace(command='command', verbose=True)
['command', '--verbose'] => Namespace(command='command', verbose=True)
['--verbose', 'command', '--verbose'] => Namespace(command='command', verbose=True)

# using distinctive args
['--verbose', 'command'] => Namespace(command='command', verbose(main)=True, verbose(subcommand)=False)
['command', '--verbose'] => Namespace(command='command', verbose(main)=False, verbose(subcommand)=True)
['--verbose', 'command', '--verbose'] => Namespace(command='command', verbose(main)=True, verbose(subcommand)=True)
msg165449 - (view) Author: Samwyse (samwyse) * Date: 2012-07-14 13:55
One change and one minor problem with my suggestion.

First, you don't need the second alias, since it's a prefix of the argument name.  Also, HelpFormatter._format_actions_usage ends with a bit of code labeled "clean up separators for mutually exclusive groups"; it removes matched parentheses from the argument names.  :(  I'd recommend that you instead use one of the following (all of which I've tested):

    parser.add_argument('--verbose[main]', ...)
    parser.add_argument('--verbose{main}', ...)
    parser.add_argument('--verbose<main>', ...)
msg166184 - (view) Author: Steven Bethard (bethard) * (Python committer) Date: 2012-07-22 23:53
I don't think there's any easy way for argparse to automatically do what you want. However, there's a simple workaround - just use the dest= argument and specify two different destinations:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--verbose', action='store_true', dest='verbose_main')
>>> subparsers = parser.add_subparsers(help='command', dest='command')
>>> cmd1_parser = subparsers.add_parser('command')
>>> cmd1_parser.add_argument('--verbose', action='store_true', dest='verbose_sub')
>>> parser.parse_args(['command', '--verbose'])
Namespace(command='command', verbose_main=False, verbose_sub=True)
>>> parser.parse_args(['--verbose', 'command'])
Namespace(command='command', verbose_main=True, verbose_sub=False)

Closing as a wontfix, but feel free to reopen if you want to provide a patch for something.
msg166186 - (view) Author: Steven Bethard (bethard) * (Python committer) Date: 2012-07-23 00:01
If you'd like to help improve the documentation so that the workaround for your problem is more obvious, please contribute to Issue 15428.
Date User Action Args
2022-04-11 14:57:32adminsetgithub: 59532
2018-05-26 16:18:56paul.j3setnosy: + paul.j3
2012-07-23 00:01:41bethardsetmessages: + msg166186
2012-07-22 23:53:40bethardsetstatus: open -> closed
resolution: wont fix
messages: + msg166184

versions: - Python 2.7, Python 3.2, Python 3.3
2012-07-14 13:55:56samwysesetmessages: + msg165449
2012-07-14 12:05:16samwysesetfiles: +
nosy: + samwyse
messages: + msg165441

2012-07-13 19:43:06ezio.melottisetnosy: + ezio.melotti
stage: test needed
type: enhancement -> behavior

versions: + Python 3.3, Python 3.4, - Python 2.6, Python 3.1
2012-07-13 18:54:58tshepangsetnosy: + bethard, tshepang
2012-07-11 11:05:29Ingo.Fischercreate