https://github.com/python/cpython/commit/f282f7aed91a872078ea88df3d22a780bbd7bee0
commit: f282f7aed91a872078ea88df3d22a780bbd7bee0
branch: main
author: Filipe Laíns <[email protected]>
committer: FFY00 <[email protected]>
date: 2026-02-19T16:10:58Z
summary:

GH-134872: add ModuleNotFoundError suggestions (#142512)

* gh-134872: Add traceback suggestions for ModuleNotFoundError

Signed-off-by: Filipe Laíns <[email protected]>

* Add news

Signed-off-by: Filipe Laíns <[email protected]>

---------

Signed-off-by: Filipe Laíns <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-02-19-15-42-06.gh-issue-134872.sjYX1-.rst
M Lib/traceback.py

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)
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`.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to