[issue9938] Documentation for argparse interactive use
New submission from Jay T <jaytula@gmail.com>: I want to create a custom interactive shell where I continually do parse_args. Like the following: parser = argparse.ArgumentParser() command = raw_input() while(True): args = parser.parse_args(shlex.split(command)) # Do some magic stuff command = raw_input() The problem is that if I give it invalid input, it errors and exits with a help message. I learned from argparse-users group that you can override the exit method like the following: class MyParser(ArgumentParser): def exit(self, status=0, message=None): # do whatever you want here I would be nice to have this usage documented perhaps along with best practices for doing help messages in this scenario. ---------- assignee: docs@python components: Documentation messages: 117287 nosy: docs@python, jayt priority: normal severity: normal status: open title: Documentation for argparse interactive use type: feature request versions: Python 2.7 _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Changes by Steven Bethard <steven.bethard@gmail.com>: ---------- nosy: +bethard versions: +Python 3.2 _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Éric Araujo <merwok@netwok.org> added the comment: Do you want to work on a patch? (Aside: you may want to learn about the cmd and shlex modules for read-eval-print-loop programs :) ---------- keywords: +easy nosy: +eric.araujo _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Tan Zong Xuan <tzxrules@gmail.com> added the comment: I am also trying to use argparse interactively, but in this case by combining it with the cmd module. So I'm doing something like below: class MyCmd(cmd.Cmd): parser = argparse.ArgumentParser(prog='addobject') parser.add_argument('attribute1') parser.add_argument('attribute2') parser.add_argument('attribute3') def do_addobject(self, line): args = MyCmd.parser.parse_args(line.split()) newobject = object(args.attribute1, args.attribute2, args.attribute3) myobjects.append(newobject) I'm faced with the same problem that when given invalid input, parse_args exits the program completely, instead of exiting just to the Cmd shell. I have the feeling that this use case is sufficiently common such that it would be good if people did not have to override the exit method themselves, and instead an alternative to parse_args was provided that only raises exceptions for the surrounding code to handle rather than exiting the program entirely. ---------- nosy: +ZOMGxuan _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Éric Araujo <merwok@netwok.org> added the comment: You can always catch SystemExit. ---------- _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Steven Bethard <steven.bethard@gmail.com> added the comment: In the short term, just catch the SystemExit. In the slightly longer term, we could certainly provide a subclass, say, ErrorRaisingArgumentParser, that overrides .exit and .error to do nothing but raise an exception with the message they would have printed. We'd probably have to introduce a new Exception subclass though, maybe ArgumentParserExit or something like that. Anyway if you're interested in this, please file a new ticket (preferably with a patch). Regardless of whether we ever provide the subclass, we certainly need to patch the documentation to tell people how to override error and exit. ---------- _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Changes by Xuanji Li <xuanji@gmail.com>: ---------- nosy: +xuanji _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Xuanji Li <xuanji@gmail.com> added the comment: I don't think it's best to create a new subclass to throw an ArgumentParserExit exception; if I read the stack trace I'd see that an ArgumentError was thrown, then caught, then an ArgumentParserExit was thrown, which IMHO is confusing. In the current design, parse_known_errors catches an ArgumentError and then exits. I propose that the user be optionally allowed to turn off the handling of ArgumentError and to handle it himself instead through an exit_on_argument_error flag. Attached patch does this. Also I think this issue falls under component 'Lib' too. ---------- components: +Library (Lib) keywords: +patch Added file: http://bugs.python.org/file21793/issue9938.patch _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Ezio Melotti <ezio.melotti@gmail.com> added the comment: FWIW unittest had a similar issue and it's been solved adding an 'exit' argument to unittest.main() [0]. I think using an attribute here might be fine. The patch contains some trailing whitespace that should be removed, also it might be enough to name the attribute "exit_on_error". It should also include tests to check that the attribute is set with the correct default value and that it doesn't raise SystemExit when the attribute is False. [0]: http://docs.python.org/library/unittest.html#unittest.main ---------- nosy: +ezio.melotti versions: +Python 3.3 _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Xuanji Li <xuanji@gmail.com> added the comment: Updated previous patch with test cases and renamed exit_on_argument_error flag to exit_on_error. ---------- Added file: http://bugs.python.org/file22172/issue9938_with_test.patch _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Steven Bethard <steven.bethard@gmail.com> added the comment: Looks good to me. ---------- _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Andrew Berg added the comment: What is the status of this? If the patch looks good, then will it be pushed into 3.4? ---------- nosy: +aberg _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
R. David Murray added the comment: It's great that this patch was provided. Xuanji, can you submit a contributor agreement, please? The patch is missing an update to the documentation. (Really the patch should have been in a separate issue, as requested, since this one is about improving the documentation for the existing released versions. I guess we'll have to open a new issue for updating the docs in the existing versions). ---------- nosy: +r.david.murray stage: -> needs patch versions: +Python 3.4 -Python 3.2 _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Andrew Berg added the comment: The patch doesn't work for 3.3 (I think it's just because the line numbers are different), but looking over what the patch does, it looks like parse_known_args will return a value for args if there is an unrecognized argument, which will cause parse_args to call error() (it should raise ArgumentError instead). ---------- _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Ethan Furman added the comment: It doesn't look like xuanji has signed a CLA. Should we create a new issue, and have someone else create a new patch, and let this issue just be about the docs? ---------- nosy: +ethan.furman _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
R. David Murray added the comment: Yes, I think opening a new issue at this point might be a good idea. The reason is that there are a changes either in place or pending in other issues that involve the parse_know_args code, so a new patch is probably required regardless. I wish I had time to review and commit all the argparse patches, but so far I haven't gotten to them. They are on my todo list somewhere, though :) ---------- _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
paul j3 added the comment: The exit and error methods are mentioned in the 3.4 documentation, but there are no examples of modifying them. 16.4.5.9. Exiting methods ArgumentParser.exit(status=0, message=None) ArgumentParser.error(message) test_argparse.py has a subclass that redefines these methods, though I think it is more complex than necessary. class ErrorRaisingArgumentParser(argparse.ArgumentParser): In http://bugs.python.org/file30204/test_intermixed.py , part of http://bugs.python.org/issue14191 , which creates a parser mode that is closer to optparse in style, I simply use: def error(self, message): usage = self.format_usage() raise Exception('%s%s'%(usage, message)) ArgumentParser.error = error to catch errors. https://github.com/nodeca/argparse a Javascript port of argparse, adds a 'debug' option to the ArgumentParser, that effectively redefines this error method. They use that extensively in testing. Another approach is to trap the sysexit. Ipython does that when argparse is run interactively. Even the simple try block works, though the SystemExit 2 has no information about the error. try: args = parser.parse_args('X'.split()) except SystemExit as e: print(e) Finally, plac ( https://pypi.python.org/pypi/plac ) is a pypi package that is built on argparse. It has a well developed interactive mode, and integrates threads and multiprocessing. ---------- nosy: +paul.j3 _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Changes by Ethan Furman <ethan@stoneleaf.us>: ---------- nosy: -ethan.furman _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Changes by Wolfgang Maier <wolfgang.maier@biologie.uni-freiburg.de>: ---------- nosy: +wolma _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Sourav Singh added the comment: I would like to send a patch for the issue. How do I start ---------- nosy: +Sourav Singh _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue9938> _______________________________________
Milan Oberkirch <milan.py@oberkirch.org> added the comment: This issue is a duplicate of issue 9112 which was resolved by commit 9375492b ---------- nosy: +zvyn _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue9938> _______________________________________
Change by hai shi <shihai1991@126.com>: ---------- pull_requests: +15073 stage: needs patch -> patch review pull_request: https://github.com/python/cpython/pull/15362 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue9938> _______________________________________
hai shi <shihai1991@126.com> added the comment: It is a good idea. So I update this title and add PR 15362. I am not sure there have a problem of xuanli's CLA or not~ ---------- components: -Documentation nosy: +shihai1991 title: Documentation for argparse interactive use -> Improving interactive use of argparse versions: +Python 3.9 -Python 2.7, Python 3.3, Python 3.4 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue9938> _______________________________________
Change by hai shi <shihai1991@126.com>: ---------- title: Improving interactive use of argparse -> Add optional kwargs to argparse _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue9938> _______________________________________
Change by hai shi <shihai1991@126.com>: ---------- nosy: +rhettinger _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue9938> _______________________________________
Change by Stéphane Wirtel <stephane@wirtel.be>: ---------- title: Add optional kwargs to argparse -> Add optional keyword argument exit_on_error to argparse.ArgumentParser _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue9938> _______________________________________
miss-islington <mariatta.wijaya+miss-islington@gmail.com> added the comment: New changeset f545638b5701652ffbe1774989533cdf5bc6631e by Miss Islington (bot) (Hai Shi) in branch 'master': bpo-9938: Add optional keyword argument exit_on_error to argparse.ArgumentParser (GH-15362) https://github.com/python/cpython/commit/f545638b5701652ffbe1774989533cdf5bc... ---------- nosy: +miss-islington _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue9938> _______________________________________
Stéphane Wirtel <stephane@wirtel.be> added the comment: Thank you for your PR and for your time, I have merged the PR into master. ---------- nosy: +matrixise resolution: -> fixed stage: patch review -> resolved status: open -> closed _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue9938> _______________________________________
hai shi <shihai1991@126.com> added the comment: Stéphane, thanks for your good comment. Some argparse's bpo is too old ;) ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue9938> _______________________________________
participants (16)
-
Andrew Berg
-
Ethan Furman
-
Ezio Melotti
-
hai shi
-
Jay T
-
Milan Oberkirch
-
miss-islington
-
paul j3
-
R. David Murray
-
Sourav Singh
-
Steven Bethard
-
Stéphane Wirtel
-
Tan Zong Xuan
-
Wolfgang Maier
-
Xuanji Li
-
Éric Araujo