Repository navigation
Argparse.parse_args exits on unrecognized option with exit_on_error=False #85427
Description
Activity
matthewhughes934 commented
on Jul 9, 2020 matthewhughes934mannequinMannequinAuthorMore actions>>> 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:
Normally, when you pass an invalid argument list to the parse_args() method of an ArgumentParser, it will exit with error info.
If the user would like catch errors manually, the feature can be enable by setting exit_on_error to False:This description _appears_ to be at odds with the observed behavior.
Reacted by Sam Steingold and John Hennig- added3.10 (EOL)end of lifeend of lifestdlibStandard 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
on 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 commented
on Jul 9, 2020 matthewhughes934mannequinMannequinAuthorMore actionstypo in the docs that it should have used enabled instead of enable
Well spotted, I'll happily fix this up.
I guess the docs by manually mean that ArgumentError will be raised when exit_on_error is False that can be handled.
To be clear, in this case, even with exit_on_error=False, ArgumentError is _not_ being raised, but SystemExit is.
matthewhughes934 commented
on Jul 9, 2020 matthewhughes934mannequinMannequinAuthorMore actionsI'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:
- An unrecognized option is given
- A required option is not given
Should the docs be updated to note this?
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
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:which takes a command name and any ArgumentParser constructor arguments, and returns an ArgumentParser object that can be modified as usual.But as my experience shows, its relevance is easily missed, even by an experienced users.
- added3.11only security fixesonly security fixes3.10 (EOL)end of lifeend of life3.12only security fixesonly security fixesand removed3.9 (EOL)end of lifeend of life
on Jun 7, 2022 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.
Reacted by psasselum, Dima Matveev, RedoX, John Hennig, Ganesh N Sivalingam and edna
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsDoc issues
ArgumentParser.exit_on_erroris False #30832Note: 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:
bugs.python.org fields: