57 5.5. The Path Based Finder The Python Language Reference, Release 3.9.5 Changed in version 3.4: Use of$_{loader.module_repr()}$ has been deprecated and the module spec is now used by the import machinery to generate a module repr. For backward compatibility with Python 3.3, the module repr will be generated by calling the loader’s module_repr() method, if defined, before trying either approach described above. However, the method is deprecated. Before Python loads cached bytecode from a$_{.pyc}$ file, it checks whether the cache is up-to-date with the source .py file. By default, Python does this by storing the source’s last-modified timestamp and size in the cache file when writing it. At runtime, the import system then validates the cache file by checking the stored metadata in the cache file against the source’s metadata. Python also supports “hash-based” cache files, which store a hash of the source file’s contents rather than its metadata. There are two variants of hash-based$_{.pyc}$ files: checked and unchecked. For checked hash-based$_{.pyc}$ files, Python validates the cache file by hashing the source file and comparing the resulting hash with the hash in the cache file. If a checked hash-based cache file is found to be invalid, Python regenerates it and writes a new checked hash- based cache file. For unchecked hash-based .pyc files, Python simply assumes the cache file is valid if it exists. Hash-based .pyc files validation behavior may be overridden with the --check-hash-based-pycs flag. Changed in version 3.7: Added hash-based$_{.pyc}$ files. Previously, Python only supported timestamp-based invali- dation of bytecode caches. 5.4.7 Cached bytecode invalidation 5.5 The Path Based Finder As mentioned previously, Python comes with several default meta path finders. One of these, called the path based finder ($_{PathFinder}$ ), searches an import path , which contains a list of path entries . Each path entry names a location to search for modules. The path based finder itself doesn’t know how to import anything. Instead, it traverses the individual path entries, associating each of them with a path entry finder that knows how to handle that particular kind of path. The default set of path entry finders implement all the semantics for finding modules on the file system, handling special file types such as Python source code ($_{.py}$files), Python byte code ($_{.pyc}$ files) and shared libraries (e.g. $_{.so}$files). When supported by the$_{zipimport}$ module in the standard library, the default path entry finders also handle loading all of these file types (other than shared libraries) from zipfiles. Path entries need not be limited to file system locations. They can refer to URLs, database queries, or any other location that can be specified as a string. The path based finder provides additional hooks and protocols so that you can extend and customize the types of searchable path entries. For example, if you wanted to support path entries as network URLs, you could write a hook that implements HTTP semantics to find modules on the web. This hook (a callable) would return a path entry finder supporting the protocol described below, which was then used to get a loader for the module from the web. A word of warning: this section and the previous both use the term finder , distinguishing between them by using the terms meta path finder and path entry finder . These two types of finders are very similar, support similar protocols, and function in similar ways during the import process, but it’s important to keep in mind that they are subtly different. In particular, meta path finders operate at the beginning of the import process, as keyed off the$_{sys.meta_path}$ traversal. By contrast, path entry finders are in a sense an implementation detail of the path based finder, and in fact, if the path based finder were to be removed from$_{sys.meta_path}$ , none of the path entry finder semantics would be invoked.