diff options
author | Nick Coghlan <ncoghlan@gmail.com> | 2006-09-07 10:50:34 (GMT) |
---|---|---|
committer | Nick Coghlan <ncoghlan@gmail.com> | 2006-09-07 10:50:34 (GMT) |
commit | c495c66ea922e3ce8d822716a7abbf28ee709b71 (patch) | |
tree | 27b8b57601634af058d059f58fb30777c1401e86 /Lib/inspect.py | |
parent | c563a1c32b136b5f4d65658d3f5487be206c104b (diff) | |
download | cpython-c495c66ea922e3ce8d822716a7abbf28ee709b71.zip cpython-c495c66ea922e3ce8d822716a7abbf28ee709b71.tar.gz cpython-c495c66ea922e3ce8d822716a7abbf28ee709b71.tar.bz2 |
Fix the speed regression in inspect.py by adding another cache to speed up getmodule(). Patch #1553314
Diffstat (limited to 'Lib/inspect.py')
-rw-r--r-- | Lib/inspect.py | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py index 0b498b5..ba2021a 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -403,6 +403,7 @@ def getabsfile(object, _filename=None): return os.path.normcase(os.path.abspath(_filename)) modulesbyfile = {} +_filesbymodname = {} def getmodule(object, _filename=None): """Return the module an object was defined in, or None if not found.""" @@ -410,19 +411,32 @@ def getmodule(object, _filename=None): return object if hasattr(object, '__module__'): return sys.modules.get(object.__module__) + # Try the filename to modulename cache + if _filename is not None and _filename in modulesbyfile: + return sys.modules.get(modulesbyfile[_filename]) + # Try the cache again with the absolute file name try: file = getabsfile(object, _filename) except TypeError: return None if file in modulesbyfile: return sys.modules.get(modulesbyfile[file]) - for module in sys.modules.values(): + # 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.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__'): return None @@ -430,6 +444,7 @@ def getmodule(object, _filename=None): mainobject = getattr(main, object.__name__) if mainobject is object: return main + # Check builtins builtin = sys.modules['__builtin__'] if hasattr(builtin, object.__name__): builtinobject = getattr(builtin, object.__name__) @@ -444,7 +459,7 @@ def findsource(object): in the file and the line number indexes a line in that list. An IOError is raised if the source code cannot be retrieved.""" file = getsourcefile(object) or getfile(object) - module = getmodule(object) + module = getmodule(object, file) if module: lines = linecache.getlines(file, module.__dict__) else: |