Closed
Labels
3.10 (EOL)end of lifeend of life3.11only security fixesonly security fixes3.12only security fixesonly security fixesstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
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 2020-07-09.08:40:33.198>
labels = ['type-bug', 'library', '3.9']
title = 'Argparse.parse_args exits on unrecognized option with exit_on_error=False'
updated_at = <Date 2022-01-29.03:10:17.942>
user = 'https://github.com/matthewhughes934'bugs.python.org fields:
activity = <Date 2022-01-29.03:10:17.942>
actor = 'jacobtylerwalls'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)']
creation = <Date 2020-07-09.08:40:33.198>
creator = 'mhughes'
dependencies = []
files = ['49310']
hgrepos = []
issue_num = 41255
keywords = ['patch']
message_count = 10.0
messages = ['373382', '373383', '373385', '373405', '373437', '373440', '373470', '396345', '397975', '401629']
nosy_count = 7.0
nosy_names = ['rhettinger', 'paul.j3', 'xtreak', 'mhughes', 'jacobtylerwalls', 'bigbird', 'joshmeranda']
pr_nums = ['27295', '30832']
priority = 'normal'
resolution = None
stage = 'patch review'
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue41255'
versions = ['Python 3.9']Reacted by Ioannis Triantafillou, psasselum, Joakim Joensuu, RedoX and John Hennig
Metadata
Metadata
Assignees
Labels
3.10 (EOL)end of lifeend of life3.11only security fixesonly security fixes3.12only security fixesonly security fixesstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Projects
- StatusShow more project fieldsDoc issues
Activity
matthewhughes934 commentedon Jul 9, 2020
>>> import argparse >>> parser = argparse.ArgumentParser(exit_on_error=False) >>> parser.parse_args(["--unknown"]) usage: [-h] : error: unrecognized arguments: --unknownThe docs https://docs.python.org/3.10/library/argparse.html#exit-on-error say:
This description _appears_ to be at odds with the observed behavior.
tirkarthi commentedon Jul 9, 2020
I guess the docs by manually mean that ArgumentError will be raised when exit_on_error is False that can be handled. By default with exit_on_error being True self.error() which raises SystemExit and catching SystemExit can mask other errors. This was added in bpo-9938 with #59567. There is also a typo in the docs that it should have used enabled instead of enable in "the feature can be enable by setting exit_on_error to False"
matthewhughes934 commentedon Jul 9, 2020
Well spotted, I'll happily fix this up.
To be clear, in this case, even with exit_on_error=False, ArgumentError is _not_ being raised, but SystemExit is.
matthewhughes934 commentedon Jul 9, 2020
I've attached a patch containing tests showing the current behavior, namely that exit_on_error does not change the behavior of argparse.ArgumentParser.parse_args in either case:
Should the docs be updated to note this?
paulj3 commentedon Jul 10, 2020
I didn't pay attention to the patch that added this "exit_on_error" parameter. So I don't know exactly what error handling it was supposed to handle or why. But given the location of the code change, it does not handle every possible error.
Specifically it's in parser.parse_known_args() where it calls _parse_known_args(). With this parameter True, a argparse.ArgumentError is caught and converted to parse.error() call. That's the original behavior.
With False, there's no special handling for ArgumentError. Catching that is left to the developer, as illustrated in the docs.
In the documented example, it's a 'type' error. 'choices' would also behave this way. 'nargs' errors also. But not all errors are handled like this.
Inside _parse_known_args(),
self.error()is called several times, once for 'required' arguments failure, and for a required mutually_exclusive_group error. I count 9 self.error() calls; exit_on_error only changes one of those.The error highlighted in this issue is called in parser.parse_args(). This calls parse_known_args(), and raises an error if there are 'extras', unrecognized strings.
So clearly the new docs is is describing this new parameter in overly broad terms. It only changes the handling of a subset of parser.error() calls. Off hand I can't think of clean way of refining the description without getting overly technical about the error handling.
Developers already had the documented option of changing the parse.error() and parse.exit() methods.
5 remaining items
paulj3 commentedon Sep 11, 2021
In
https://stackoverflow.com/questions/69108632/unable-to-catch-exception-error-for-argparse
it looked like
exit_on_errordoes not work when using subparsers. On on further thought, I realized that it has to included in the definition of the subparser. As with otherArgumentParserparameters, the subparsers does not inherit from the main parser.So it's basically a documentation issue. The
add_parsermethod is described briefly as:But as my experience shows, its relevance is easily missed, even by an experienced users.
ed-ij commentedon Mar 31, 2023
Just wanted to bump this after attempting to use the
exit_on_errorargument to preventsys.exit()being called.The documentation could at least be improved until a better implementation is available. Adding a note in the documentation for this function which links to the "Exiting methods" section would also be helpful in the interim although I agree with bigbirdcode and joshmeranda that you shouldn't have to override methods just to have control over error handling.
serhiy-storchaka commentedon Jun 26, 2024
I wrote #121056 before discovering this issue. It is basically an extended version of #30832.
We now have 3 duplicate issues with 4 open PRs (and one incomplete PR was already merged). It is time to finish this.