diff -r 63a1ee94b3ed Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py Thu Oct 10 00:46:57 2013 -0700 +++ b/Lib/importlib/_bootstrap.py Thu Oct 10 13:18:34 2013 +0200 @@ -24,6 +24,23 @@ _CASE_INSENSITIVE_PLATFORMS = 'win', 'cygwin', 'darwin' +_stat_cache = {} +def _cached_stat(path): + cached = _stat_cache.get(path) + if cached is not None: + if isinstance(cached, OSError): + raise cached + else: + return cached + + try: + stat = _os.stat(path) + except OSError as e: + _stat_cache[path] = e + raise + else: + _stat_cache[path] = stat + return stat def _make_relax_case(): if sys.platform.startswith(_CASE_INSENSITIVE_PLATFORMS): @@ -68,7 +85,7 @@ def _path_is_mode_type(path, mode): """Test whether the path is the specified mode type.""" try: - stat_info = _os.stat(path) + stat_info = _cached_stat(path) except OSError: return False return (stat_info.st_mode & 0o170000) == mode @@ -456,7 +473,7 @@ def _calc_mode(path): """Calculate the mode permissions for a bytecode file.""" try: - mode = _os.stat(path).st_mode + mode = _cached_stat(path).st_mode except OSError: mode = 0o666 # We always ensure write access so we can update cached files @@ -878,7 +895,7 @@ if filepath is None: return None try: - _os.stat(filepath) + _cached_stat(filepath) except OSError: return None for loader, suffixes in _get_supported_file_loaders(): @@ -1072,7 +1089,7 @@ def path_stats(self, path): """Return the metadata for the path.""" - st = _os.stat(path) + st = _cached_stat(path) return {'mtime': st.st_mtime, 'size': st.st_size} def _cache_bytecode(self, source_path, bytecode_path, data): @@ -1390,7 +1407,7 @@ is_namespace = False tail_module = fullname.rpartition('.')[2] try: - mtime = _os.stat(self.path).st_mtime + mtime = _cached_stat(self.path).st_mtime except OSError: mtime = -1 if mtime != self._path_mtime: