From cb38aa40d5ea5129a0c61c3ec077657a7c441810 Mon Sep 17 00:00:00 2001 From: Locked-chess-official <13140752715@163.com> Date: Mon, 30 Mar 2026 21:08:41 +0800 Subject: [PATCH 1/3] check type in _find_incompatible_extension_module and add try-except --- Lib/traceback.py | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/Lib/traceback.py b/Lib/traceback.py index 1f9f151ebf5d39..dcf2d04b0d3eee 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -1907,26 +1907,29 @@ def _find_incompatible_extension_module(module_name): import importlib.machinery import importlib.resources.readers - if not module_name or not importlib.machinery.EXTENSION_SUFFIXES: + if not isinstance(module_name, str) or not importlib.machinery.EXTENSION_SUFFIXES: return # We assume the last extension is untagged (eg. .so, .pyd)! # tests.test_traceback.MiscTest.test_find_incompatible_extension_modules # tests that assumption. - untagged_suffix = importlib.machinery.EXTENSION_SUFFIXES[-1] - # On Windows the debug tag is part of the module file stem, instead of the - # extension (eg. foo_d.pyd), so let's remove it and just look for .pyd. - if os.name == 'nt': - untagged_suffix = untagged_suffix.removeprefix('_d') - - parent, _, child = module_name.rpartition('.') - if parent: - traversable = importlib.resources.files(parent) - else: - traversable = importlib.resources.readers.MultiplexedPath( - *map(pathlib.Path, filter(os.path.isdir, sys.path)) - ) + try: + untagged_suffix = importlib.machinery.EXTENSION_SUFFIXES[-1] + # On Windows the debug tag is part of the module file stem, instead of the + # extension (eg. foo_d.pyd), so let's remove it and just look for .pyd. + if os.name == 'nt': + untagged_suffix = untagged_suffix.removeprefix('_d') + + parent, _, child = module_name.rpartition('.') + if parent: + traversable = importlib.resources.files(parent) + else: + traversable = importlib.resources.readers.MultiplexedPath( + *map(pathlib.Path, filter(os.path.isdir, sys.path)) + ) - for entry in traversable.iterdir(): - if entry.name.startswith(child + '.') and entry.name.endswith(untagged_suffix): - return entry.name + for entry in traversable.iterdir(): + if entry.name.startswith(child + '.') and entry.name.endswith(untagged_suffix): + return entry.name + except Exception: + return From 9aa6631a580dfc948ed731148caffbabbecaef19 Mon Sep 17 00:00:00 2001 From: Locked-chess-official <13140752715@163.com> Date: Mon, 30 Mar 2026 21:11:13 +0800 Subject: [PATCH 2/3] add news --- .../next/Library/2026-03-30-21-11-02.gh-issue-146632.cDa6Yp.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2026-03-30-21-11-02.gh-issue-146632.cDa6Yp.rst diff --git a/Misc/NEWS.d/next/Library/2026-03-30-21-11-02.gh-issue-146632.cDa6Yp.rst b/Misc/NEWS.d/next/Library/2026-03-30-21-11-02.gh-issue-146632.cDa6Yp.rst new file mode 100644 index 00000000000000..5a959efe1695dd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-30-21-11-02.gh-issue-146632.cDa6Yp.rst @@ -0,0 +1 @@ +Add type check and use try-except to fix traceback crash From f0aec1f29611950c573733b6961527edb9e7df5b Mon Sep 17 00:00:00 2001 From: Locked-chess-official <13140752715@163.com> Date: Tue, 31 Mar 2026 00:03:57 +0800 Subject: [PATCH 3/3] add a test on wrong name in ModuleNotFoundError --- Lib/test/test_traceback.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 5dc11253e0d5c8..d9e1c0bb3069de 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -5456,5 +5456,17 @@ def test_suggestion_still_works_for_non_lazy_attributes(self): self.assertNotIn(b"BAR_MODULE_LOADED", stdout) +class TestNoCrashInTracebackException(unittest.TestCase): + def test_module_not_found_error_with_bad_name(self): + exc = ModuleNotFoundError(name=NotImplemented) + try: + te = traceback.TracebackException.from_exception(exc) + except Exception as e: + self.fail(f"TracebackException raised unexpected exception: {e!r}") + else: + msg = "".join(te.format()) + self.assertEqual(msg, "ModuleNotFoundError\n") + + if __name__ == "__main__": unittest.main()