From c739aa6d94bb2a894d9b57e012a70467f5d9d845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Fri, 10 Oct 2025 14:05:13 +0100 Subject: [PATCH 1/2] gh-134872: Add traceback suggestions for ModuleNotFoundError MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Filipe Laíns --- Lib/traceback.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Lib/traceback.py b/Lib/traceback.py index 42453b4867ce99..b16cd8646e43f1 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -11,6 +11,7 @@ import keyword import tokenize import io +import importlib.util import _colorize from contextlib import suppress @@ -1128,6 +1129,10 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, self._str += (". Site initialization is disabled, did you forget to " + "add the site-packages directory to sys.path " + "or to enable your virtual environment?") + else: + suggestion = _compute_suggestion_error(exc_value, exc_traceback, module_name) + if suggestion: + self._str += f". Did you mean: '{suggestion}'?" elif exc_type and issubclass(exc_type, AttributeError) and \ getattr(exc_value, "name", None) is not None: wrong_name = getattr(exc_value, "name", None) @@ -1717,6 +1722,18 @@ def _compute_suggestion_error(exc_value, tb, wrong_name): d = [x for x in d if x[:1] != '_'] except Exception: return None + elif isinstance(exc_value, ModuleNotFoundError): + try: + if parent_name := wrong_name.rpartition('.')[0]: + parent = importlib.util.find_spec(parent_name) + else: + parent = None + d = [] + for finder in sys.meta_path: + if discover := getattr(finder, 'discover', None): + d += [spec.name for spec in discover(parent)] + except Exception: + return None elif isinstance(exc_value, ImportError): try: mod = __import__(exc_value.name) From fb57d7d73855c7f8c131ea0ba624554a62a298b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Thu, 19 Feb 2026 15:42:18 +0000 Subject: [PATCH 2/2] Add news MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Filipe Laíns --- .../next/Library/2026-02-19-15-42-06.gh-issue-134872.sjYX1-.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2026-02-19-15-42-06.gh-issue-134872.sjYX1-.rst diff --git a/Misc/NEWS.d/next/Library/2026-02-19-15-42-06.gh-issue-134872.sjYX1-.rst b/Misc/NEWS.d/next/Library/2026-02-19-15-42-06.gh-issue-134872.sjYX1-.rst new file mode 100644 index 00000000000000..4654dd060a6b78 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-19-15-42-06.gh-issue-134872.sjYX1-.rst @@ -0,0 +1 @@ +Add valid import name suggestions on :exc:`ModuleNotFoundError`.