Skip to main content

Import system

import is a high-level statement backed by __import__, which is itself a thin wrapper over importlib._bootstrap._find_and_load. This page documents the protocol from statement through bytecode through finder/loader machinery.

Source-of-record: CPython import system, Lib/importlib/, Python/import.c.

The import statement

Forms

FormResult
import aBinds a to the top-level module.
import a.b.cImports a, a.b, a.b.c; binds a.
import a as xBinds x to module a.
import a.b.c as xBinds x to module a.b.c.
from a import bBinds b from module a (attribute or submodule).
from a import b as xAs above, bound as x.
from a import b, cMultiple bindings.
from a import *Binds every public name (per __all__).
from . import bRelative import, current package.
from .. import bRelative import, parent package.
from ..a.b import cRelative import, deeper path.

Relative imports require the current module to have a __package__ attribute.

Bytecode emission

SourceApproximate bytecode
import aLOAD_CONST None; LOAD_CONST None; IMPORT_NAME 'a'; STORE_NAME 'a'.
import a.bIMPORT_NAME 'a.b'; STORE_NAME 'a'.
from a import bIMPORT_NAME 'a'; IMPORT_FROM 'b'; STORE_NAME 'b'.
from a import *IMPORT_NAME 'a'; IMPORT_STAR.

IMPORT_NAME consumes a level (negative for relative) and a fromlist tuple from the stack.

Module resolution

The high-level algorithm:

  1. Cache lookup. Check sys.modules[name]. If present and not None, return it.
  2. Parent. If name has dots, recursively import the parent.
  3. Finder loop. Iterate sys.meta_path; for each finder call find_spec(name, path).
  4. Spec. The first non-None spec is used. If no finder returns, raise ModuleNotFoundError.
  5. Load. Use the spec's loader to create and execute the module.
  6. Cache. Store the module in sys.modules.
  7. Bind. If the parent is a package, bind the submodule as an attribute of the parent.

Finders

A finder is an object with find_spec(name, path, target=None).

Built-in meta-path finders

In order:

FinderRole
BuiltinImporterC-implemented modules in the interpreter's inittab.
FrozenImporterModules frozen into the interpreter binary.
PathFinderSearches sys.path using sys.path_hooks.

Path-based finders

PathFinder walks sys.path. For each entry it consults sys.path_importer_cache, falling back to sys.path_hooks to construct a path entry finder.

Default path entry finders:

FinderHandles
FileFinder with SourceFileLoader.py source files.
FileFinder with SourcelessFileLoader.pyc cached bytecode.
FileFinder with ExtensionFileLoader.so / .pyd extension modules (CPython only).

Loaders

A loader is an object that creates and executes the module.

Loader protocol

MethodRole
create_module(spec)Construct the module object. Return None for default.
exec_module(module)Populate the module's namespace by executing its code.
get_code(name)Optional; return a code object. Used by runpy.
get_source(name)Optional; return source text.
is_package(name)Optional; True if the loader treats the name as a package.
get_filename(name)Optional; the file path backing the module.
get_data(path)Optional; raw bytes at a relative path.

Common loaders

LoaderWhat it loads
SourceFileLoader.py, with .pyc caching.
SourcelessFileLoader.pyc without source.
ExtensionFileLoaderC extensions (not in gopy).
_LoaderBasicsBase class for namespace packages.
BuiltinImporterBuilt-in modules registered via inittab.
FrozenImporterModules frozen via freeze_module.

Module specs

ModuleSpec(name, loader, origin=None, ...) carries everything needed to load a module:

FieldMeaning
nameFully qualified import name.
loaderThe loader instance.
originSource location string.
submodule_search_locationsList of paths if this is a package; None otherwise.
loader_stateLoader-private data.
cachedPath to .pyc, if any.
parentParent package name.
has_locationbool(origin).

Packages

A package is a module whose __path__ attribute is set. There are two kinds:

KindTrigger
Regular packageContains __init__.py.
Namespace packageHas no __init__.py; produced by PathFinder merging multiple matching path entries (PEP 420).

__path__

For regular packages, __path__ is a one-element list containing the directory. For namespace packages, it is a list of all contributing directories.

__init__.py

When importing a regular package, the runtime imports the package and executes __init__.py in the package's namespace. Submodules are imported lazily (from a import b is a normal submodule import).

sys module hooks

AttributeUsed for
sys.modulesModule cache, {name: module}.
sys.pathSearch path for PathFinder.
sys.path_hooksCallables that build path entry finders.
sys.path_importer_cache{path: finder} cache.
sys.meta_pathList of meta-path finders.
sys.builtin_module_namesNames of built-in (inittab) modules.

.pyc caching

ConceptMeaning
__pycache__/<name>.cpython-314.pycCache location.
Magic number32-bit version tag. CPython differs from gopy here.
Hash-based--check-hash-based-pycs always/default/never.
Source timestampDefault invalidation: source mtime + size.

The .pyc file layout (16-byte header + marshalled code):

OffsetSizeMeaning
04Magic number.
44Source mtime (or hash) flags.
84Source mtime or hash bytes (1).
124Source size or hash bytes (2).
16-Marshalled code object.

See Marshal format for the body.

importlib API surface

FunctionRole
importlib.import_module(name, pkg)Programmatic equivalent of the import statement.
importlib.invalidate_caches()Clear path-finder caches.
importlib.reload(module)Re-execute a module in place.
importlib.resources.*Resource access via the loader.
importlib.util.spec_from_*Build specs from a file, location, or loader.
importlib.machinery.*Concrete finder/loader classes.
importlib.abc.*Abstract base classes for finders/loaders.

__main__

The top-level script runs in a module named __main__. Three ways to enter it:

Invocation__main__ content
python3 script.pyThe script.
python3 -m pkgpkg/__main__.py from inside the package.
python3 -c "code"The string passed to -c.

Inside an interactive REPL, __main__ is also the active module.

Gopy status

AreaState
import statement and fromComplete.
Meta-path finder protocolComplete.
Path-based findersComplete for .py and .pyc.
Namespace packages (PEP 420)Complete.
Built-in modules via imp.AppendInittabComplete; see Embedding.
Frozen modulesStdlib only, via stdlibinit.
.pyc reading and writingComplete; uses gopy magic number, not CPython-interoperable.
importlib Python surfaceComplete.
C extension loadingOut of scope.

Reference