[New-bugs-announce] [issue39106] Add suggestions to argparse error message output for unrecognized arguments

Karthikeyan Singaravelan report at bugs.python.org
Fri Dec 20 03:56:09 EST 2019


New submission from Karthikeyan Singaravelan <tir.karthi at gmail.com>:

I came across this idea while working on error messages for click at https://github.com/pallets/click/issues/1446. Currently for unknown arguments which could in some case be typos argparse throws an error but doesn't make any suggestions. It could do some heuristic to suggest matches. The unrecognized argument error prints all unrecognized arguments so in that case it will be less useful to mix match suggestions. It can be helpful for single argument usages. argparse is performance sensitive since it's used in cli environments so I feel the tradeoff to do simple match to make suggestions as a good user experience.

# ssl_helper.py

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--include-ssl', action='store_true')
namespace = parser.parse_args()

No suggestions are included currently

$ python3.8 ssl_helper.py --include-ssll
usage: ssl_helper.py [-h] [--include-ssl]
ssl_helper.py: error: unrecognized arguments: --include-ssll

Include suggestions based when one of the option starts with the argument supplied similar to click

$ ./python.exe ssl_helper.py --include-ssll
usage: ssl_helper.py [-h] [--include-ssl]
ssl_helper.py: error: unrecognized argument: --include-ssll . Did you mean --include-ssl?

difflib.get_close_matches could also provide better suggestions in some cases but comes at import cost and could be imported only during error messages as proposed in the click issue

./python.exe ssl_helper.py --exclude-ssl
usage: ssl_helper.py [-h] [--include-ssl]
ssl_helper.py: error: unrecognized argument: --exclude-ssl . Did you mean --include-ssl?


Attached is a simple patch of the implementation with startswith which is more simple and difflib.get_close_matches

diff --git Lib/argparse.py Lib/argparse.py
index 5d3ce2ad70..e10a4f0c9b 100644
--- Lib/argparse.py
+++ Lib/argparse.py
@@ -1818,8 +1818,29 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
     def parse_args(self, args=None, namespace=None):
         args, argv = self.parse_known_args(args, namespace)
         if argv:
-            msg = _('unrecognized arguments: %s')
-            self.error(msg % ' '.join(argv))
+            suggestion = None
+            if len(argv) == 1:
+                argument = argv[0]
+
+                # simple startswith
+                for option in self._option_string_actions:
+                    if argument.startswith(option):
+                        suggestion = option
+                        break
+
+                # difflib impl
+                import difflib
+                try:
+                    suggestion = difflib.get_close_matches(argv[0], self._option_string_actions, n=1)[0]
+                except IndexError:
+                    pass
+
+            if suggestion:
+                msg = _('unrecognized argument: %s . Did you mean %s?')
+                self.error(msg % (' '.join(argv), suggestion))
+            else:
+                msg = _('unrecognized arguments: %s')
+                self.error(msg % ' '.join(argv))
         return args
 
     def parse_known_args(self, args=None, namespace=None):

----------
components: Library (Lib)
messages: 358699
nosy: paul.j3, rhettinger, xtreak
priority: normal
severity: normal
status: open
title: Add suggestions to argparse error message output for unrecognized arguments
type: enhancement
versions: Python 3.9

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue39106>
_______________________________________


More information about the New-bugs-announce mailing list