You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Positional arguments with boolean actions behave differently #85935
argparse allow the use of store_true and store_false for positional arguments, and although it is weird, it should be fine, but using either action raises a behavior I believe is wrong.
(add to the end of the output the value of the argument.)
Even if the use of a positional value is not the best way to describe boolean parameter (optional arguments provide a much better interface for such values), if argparse is to support positional boolean values they should work as other positional arguments.
I'd suggest raising an error if store_true or store_false is used along with positional values.
You think the behavior is wrong. Does it disagree with the doc? If not, this is an design change (enhancement) issue limited to future version. If so, it might be a bug that can be backported.
However, when I run the code on Windows with an argument
f:\dev\3x>py -3.8 f:/python/a/tem3.py a b
usage: tem3.py [-h]
...
I do not get an error, but get the same usage message as without. Adding quotes on the command line makes no difference.
changed the title [-]Positional arguments which use store boolean actions do not behave as other actions.[/-][+]Positional arguments with boolean actions behave differently[/+]on Sep 18, 2020
changed the title [-]Positional arguments which use store boolean actions do not behave as other actions.[/-][+]Positional arguments with boolean actions behave differently[/+]on Sep 18, 2020
paulj3 commented on Sep 21, 2020
paulj3mannequin
Mannequin
More actions
'store_true/false' are subclasses of 'store_const'. All have a 'nargs=0' value. It's that value which explains their behavior. ('append_const' would also fall in this category)
Like '*' and '?' this argument is 'satisfied' with nothing, an empty list of values. For those nargs, 'get_values' takes a the special step of assigning the default. For 'store_const' it's the 'const' that's placed in the namespace. 'store_true' does store True, and 'store_false' does store False.
Providing a string produces an error because there isn't any Action to consume it. With nargs=0, this Action can't use it. Usage is also correct since we can't provide any string to meet this Action's needs.
Technically then the Action behaves correctly - both in usage and what it does. That said, it normally isn't useful, since it will always assign the 'const/True/False' to the namespace. Even without an in depth knowledge of how parsing is done, this should be logically evident (if not obvious).
I don't recall any previous issues like this, though I wouldn't be surprised if there were. I don't recall anything on Stackoverflow either.
I think adding an error would be overkill. It doesn't come up often, and some user might have their own obscure reason for using it.
A note to the docs might be in order, but until a user has encountered this behavior as you have, such a note might be more confusing than useful.
As a general rule, parameter checking in add_argument() is rather loose (and multilayered). While 'action' is used to select the Action subclass, most of the rest are passed on to that Action. The Action __init__ check a few key parameters (for example 'store_const' will complain if we don't provide a 'const'), but accept or ignore the rest.
rjeffman commented on Sep 21, 2020
rjeffmanmannequin
MannequinAuthor
More actions
I don't think many users will try to use a boolean positional argument. I only excited this behavior because I was writing an abstraction over argparse to define the command line interface based on a configuration file, and I was trying to add some type checking.
There are checks for 'store' and 'append' actions:
ifnargs==0:
raiseValueError('nargs for store actions must be != 0; if you ''have nothing to store, actions such as store ''true or store const may be more appropriate')
ifnargs==0:
raiseValueError('nargs for append actions must be != 0; if arg ''strings are not supplying the value to append, ''the append const action may be more appropriate')
They were here from the initial release of argparse.
There are also few general checks in add_argument().
So there are precedences. We can either add checks in constructors of BooleanOptionalAction, _StoreConstAction, _AppendConstAction, _CountAction, _HelpAction and _VersionAction, or add a general check in add_argument(). The latter looks easier.
I wonder if there is a case for an "anchor" action. For example, subparsers could have a positional argument with action='store_const' and difference const values, so the stored value would indicate what subparser was executed. But the same goal can be achieved by using dest in add_subparsers() or set_defaults() for subparser.
Activity
rjeffman commentedon Sep 12, 2020
argparse allow the use of
store_trueandstore_falsefor positional arguments, and although it is weird, it should be fine, but using either action raises a behavior I believe is wrong.Given the following Python code:
The output is:
Note that the positional argument is not shown in the
usageline.When any string parameter is given, the result is:
(add to the end of the output the value of the argument.)
Even if the use of a positional value is not the best way to describe boolean parameter (optional arguments provide a much better interface for such values), if argparse is to support positional boolean values they should work as other positional arguments.
I'd suggest raising an error if store_true or store_false is used along with positional values.
terryjreedy commentedon Sep 18, 2020
You think the behavior is wrong. Does it disagree with the doc? If not, this is an design change (enhancement) issue limited to future version. If so, it might be a bug that can be backported.
However, when I run the code on Windows with an argument
f:\dev\3x>py -3.8 f:/python/a/tem3.py a b
usage: tem3.py [-h]
...
I do not get an error, but get the same usage message as without. Adding quotes on the command line makes no difference.
[-]Positional arguments which use store boolean actions do not behave as other actions.[/-][+]Positional arguments with boolean actions behave differently[/+][-]Positional arguments which use store boolean actions do not behave as other actions.[/-][+]Positional arguments with boolean actions behave differently[/+]paulj3 commentedon Sep 21, 2020
'store_true/false' are subclasses of 'store_const'. All have a 'nargs=0' value. It's that value which explains their behavior. ('append_const' would also fall in this category)
Like '*' and '?' this argument is 'satisfied' with nothing, an empty list of values. For those nargs, 'get_values' takes a the special step of assigning the default. For 'store_const' it's the 'const' that's placed in the namespace. 'store_true' does store True, and 'store_false' does store False.
Providing a string produces an error because there isn't any Action to consume it. With nargs=0, this Action can't use it. Usage is also correct since we can't provide any string to meet this Action's needs.
Technically then the Action behaves correctly - both in usage and what it does. That said, it normally isn't useful, since it will always assign the 'const/True/False' to the namespace. Even without an in depth knowledge of how parsing is done, this should be logically evident (if not obvious).
I don't recall any previous issues like this, though I wouldn't be surprised if there were. I don't recall anything on Stackoverflow either.
I think adding an error would be overkill. It doesn't come up often, and some user might have their own obscure reason for using it.
A note to the docs might be in order, but until a user has encountered this behavior as you have, such a note might be more confusing than useful.
As a general rule, parameter checking in add_argument() is rather loose (and multilayered). While 'action' is used to select the Action subclass, most of the rest are passed on to that Action. The Action __init__ check a few key parameters (for example 'store_const' will complain if we don't provide a 'const'), but accept or ignore the rest.
rjeffman commentedon Sep 21, 2020
I don't think many users will try to use a boolean positional argument. I only excited this behavior because I was writing an abstraction over argparse to define the command line interface based on a configuration file, and I was trying to add some type checking.
I think documenting the behavior is enough.
serhiy-storchaka commentedon Sep 25, 2024
See also #97848,
serhiy-storchaka commentedon Oct 1, 2024
There are checks for 'store' and 'append' actions:
They were here from the initial release of argparse.
There are also few general checks in
add_argument().So there are precedences. We can either add checks in constructors of
BooleanOptionalAction,_StoreConstAction,_AppendConstAction,_CountAction,_HelpActionand_VersionAction, or add a general check inadd_argument(). The latter looks easier.I wonder if there is a case for an "anchor" action. For example, subparsers could have a positional argument with
action='store_const'and differenceconstvalues, so the stored value would indicate what subparser was executed. But the same goal can be achieved by usingdestinadd_subparsers()orset_defaults()for subparser.pythongh-85935: Check for nargs=0 for positional arguments in argparse
3 remaining items
pythongh-85935: Improve tests for invalid arguments in test_argparse (p…
[3.13] pythongh-85935: Improve tests for invalid arguments in test_ar…
[3.12] gh-85935: Improve tests for invalid arguments in test_argparse (…
[3.13] gh-85935: Improve tests for invalid arguments in test_argparse (…
pythongh-85935: Excplicitly document the case nargs=0 in argparse
pythongh-85935: Excplicitly document the case nargs=0 in argparse
gh-85935: Explicitly document the case nargs=0 in argparse (GH-125302)
pythongh-85935: Explicitly document the case nargs=0 in argparse (pyt…
pythongh-85935: Explicitly document the case nargs=0 in argparse (pyt…
[3.12] gh-85935: Explicitly document the case nargs=0 in argparse (GH…
[3.13] gh-85935: Explicitly document the case nargs=0 in argparse (GH…
gh-85935: Check for nargs=0 for positional arguments in argparse (GH-…