Python IMPORT
What is the exact syntax of the python import
command?
Clarifying terminology
The language used for describing the import mechanism is confusing, often horribly so. Let's go with some clarification first.
When the 'import
Only the first three matter for our purposes.
Finding is the act of identifying the a resource that can be compiled into a meaningful Python module. This resource could a file on a filesystem, a cell in a database, a remote web object, a stream of bytes in an object store, some content object in a compressed archive, or anything that can meaningfully be said described as an array of bytes. It could even be dynamically generated in some way.
Finding typically involves scanning a collection of resources against a collection of finders. Finding ends when "finder A, given fullname B, reports that a corresponding module can be found in resource C, and that the resource can be loaded with loader D."
Finders come first, and MetaFinders come before all other kinds of finders.
Most finding is done in the context of sys.path
; that is, Python's primary means of organizing Python modules is to have them somewhere on the local filesystem. Sometimes, however, you want to get in front of that scan. That's what you do with a MetaFinder: A MetaFinder may have its own take on what to do with sys.path
; it may choose to ignore sys.path
entirely and do something with the import fullname that has nothing to do with the local filesystem.
A Finder is any object with the following function: [Loader|None] find_module([self|cls], fullname:string, path:[string|None])
If find_module returns None if it cannot find a loader resource for fullname & path.
MetaFinders are placed into the list sys.meta_path
by whatever code needs a MetaFinder, and persist for the duration of the runtime provided they're not removed or replaced. Being a list, the search is ordered and first one wins. MetaFinders may be instantiated in any way the developer desires.
PathHooks are how sys.path
is scanned to determine the which Finder should be associated with a given directory path.
A PathHook is a function: [Finder|None]
A PathHook is a function that takes a given directory path and, if the PathHook can identify a corresponding Finder for the modules in that directory path, returns the Finder, otherwise it returns None.
If no sys.meta_path
finder returns a loader, the full array of sys.paths тип sys.path_hooks
is compared until a path_hook says it can handle the path and the corresponding finder says it can handle the fullname. If no match happens, Python's default import behavior is triggered.
PathHooks are placed into the list sys.path_hooks
; like sys.meta_path
, the list is ordered and first one wins.
Loaders are returned by Finders, and are constructed by Finders with whatever resources the developer specifies the Finder has and can provide.
a collection of finders the fullname (the dot-separated string passed to the import
function).
to find a corresponding python module, which is then compiled into Python bytecode and incorporated into the python runtime, where it will be accessible to the importing function or modules
MetaFinder: A python object with a single method:
(Loader|None) find_module(self, fullname:string, path:(string|None))
Python 2.7
iter_modules (iter_importers) -> calls iter_importer_modules for each importer in iter_importers
iter_importers (meta_path, get_importer) -> returns every importer in sys.meta_path + map(get_importer, sys.path)
get_importer(path):
returns a filtered list of sys.path_hooks for importers that can
handle this path; if there is no match, returns ImpImporter(),
which supplies a module iterator (ImpImporter.iter_modules) that
relies on getmodulename.
* A path_hook is a function of (path -> Maybe importer)
iter_modules(path, get_importer, prefix) -> calls iter_importer_modules for each importer returned by path.map(get_importer)
iter_importer_modules(importer) -> returns list of (filename, ispkg) for each module understood by the importer * The method called depends on the class of the importer * The default is a generic call for "no specific importer" * For FILES, iter_import_modules returns a list of files whose extensions match those in imp.get_suffixes(), which is hard- coded into the interpreter. * MEANING: Unless your importer can handle heterogenous module suffixes, SourceFiles.iter_importer_modules can only find homogeonous modules.
This relationship issue holds for Python 2.6 as well.
Python 3.3
The same issue holds, although now most of the extensions have been
moved to importlib._bootstrap.
It is the relationship between importlib.machinery.FileFinder and iterfile_finder_modules
That's killing us.