From 6a6e9c3c2ed16030bc40e2baa3a0b11b6b1a1d84 Mon Sep 17 00:00:00 2001 From: GVN8R <79755156+GVN8R@users.noreply.github.com> Date: Mon, 20 Jul 2026 23:03:38 -0500 Subject: [PATCH 1/2] inspect: optimize getmodule() lookup path Reduce overhead in inspect.getmodule(). This includes pretty minor changes, such as replacing hasattr() / getattr() pairs with getattr( ... , None), and caching frequently accessed globals and dictionaries in local variables. --- Lib/inspect.py | 83 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py index 2a14e43b66f2fac..e4125389ccb6fbf 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -925,50 +925,73 @@ def getabsfile(object, _filename=None): def getmodule(object, _filename=None): """Return the module an object was defined in, or None if not found.""" + + modules = sys.modules + get_module = modules.get + mbf = modulesbyfile + fbm = _filesbymodname + if ismodule(object): return object - if hasattr(object, '__module__'): - return sys.modules.get(object.__module__) + + module_name = getattr(object, "__module__", None) + if module_name is not None: + return get_module(module_name) # Try the filename to modulename cache - if _filename is not None and _filename in modulesbyfile: - return sys.modules.get(modulesbyfile[_filename]) + if _filename is not None: + modname = mbf.get(_filename) + if modname is not None: + return get_module(modname) + # Try the cache again with the absolute file name try: file = getabsfile(object, _filename) except (TypeError, FileNotFoundError): return None - if file in modulesbyfile: - return sys.modules.get(modulesbyfile[file]) + + modname = mbf.get(file) + if modname is not None: + return get_module(modname) + # Update the filename to module name cache and check yet again # Copy sys.modules in order to cope with changes while iterating for modname, module in sys.modules.copy().items(): - if ismodule(module) and hasattr(module, '__file__'): - f = module.__file__ - if f == _filesbymodname.get(modname, None): - # Have already mapped this module, so skip it - continue - _filesbymodname[modname] = f - f = getabsfile(module) - # Always map to the name the module knows itself by - modulesbyfile[f] = modulesbyfile[ - os.path.realpath(f)] = module.__name__ - if file in modulesbyfile: - return sys.modules.get(modulesbyfile[file]) - # Check the main module - main = sys.modules['__main__'] - if not hasattr(object, '__name__'): + if not ismodule(module): + continue + + f = getattr(module, "__file__", None) + if f is None: + continue + if f == fbm.get(modname): + continue + + fbm[modname] = f + + absf = getabsfile(module) + name = module.__name__ + mbf[absf] = name + mbf[os.path.realpath(absf)] = name + + modname = mbf.get(file) + if modname is not None: + return get_module(modname) + + objname = getattr(object, "__name__", None) + if objname is None: return None - if hasattr(main, object.__name__): - mainobject = getattr(main, object.__name__) - if mainobject is object: - return main + + # Check the main module + main = modules['__main__'] + if getattr(main, objname, None) is object: + return main + # Check builtins - builtin = sys.modules['builtins'] - if hasattr(builtin, object.__name__): - builtinobject = getattr(builtin, object.__name__) - if builtinobject is object: - return builtin + builtin = modules['builtins'] + if getattr(builtin, objname, None) is object: + return builtin + + return None class ClassFoundException(Exception): From c4ad95522962d333d5f2da5f05469cc4da76573d Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 01:02:27 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2026-07-22-01-02-26.gh-issue-92041.o4_IwG.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-07-22-01-02-26.gh-issue-92041.o4_IwG.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-07-22-01-02-26.gh-issue-92041.o4_IwG.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-22-01-02-26.gh-issue-92041.o4_IwG.rst new file mode 100644 index 000000000000000..7fc10309d80aed9 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-22-01-02-26.gh-issue-92041.o4_IwG.rst @@ -0,0 +1 @@ +This change optimizes the lookup path in inspect.getmodule() by reducing unnecessary overhead. Minor improvements include replacing hasattr() / getattr() pairs with getattr( . . . , None) to avoid redundant attribute lookups, and caching frequently accessed globals and dictionaries in local variables to reduce repeated name resolution. Together, these changes streamline the function's hot path and provide a modest performance improvement.