Skip to main content

Python/import.c

cpython 3.14 @ ab2d84fe1023/Python/import.c

Python/import.c is the C layer of the import system. It manages sys.modules, the import lock, the frozen module table, and the importlib bootstrap. The high-level __import__ built-in delegates to importlib._bootstrap._find_and_load, but all sys.modules mutations and lock acquisition happen here.

Map

LinesSymbolRole
1-300Import lock, _PyImport_AcquireLockPer-interpreter recursive import lock
301-600sys.modules helpers_PyImport_GetModuleAttrString, module cache lookup/insert
601-900PyImport_ImportModule, PyImport_ImportTop-level public API
901-1300_PyImport_FindExtensionObjectExtension module (.so/.pyd) lookup and init
1301-1700Frozen module table, PyImport_ImportFrozenModuleBuilt-in frozen module loading
1701-3000importlib bootstrap, _PyImport_InitImportFuncBootstrap handoff to importlib

Reading

Import lock

The import lock is a per-interpreter recursive mutex. A thread that already holds the lock may re-enter (for circular imports). Deadlock detection raises ImportError.

// CPython: Python/import.c:185 _PyImport_AcquireLock
_PyImport_AcquireLock(PyInterpreterState *interp)
{
_PyRecursiveMutex_Lock(&interp->imports.lock);
}

sys.modules cache

Every import begins with a sys.modules lookup. The cache stores the fully initialized module object. A partially-initialized module is also placed in sys.modules before execution so that circular imports find a module object rather than triggering a second import.

// CPython: Python/import.c:470 import_get_module
static PyObject *
import_get_module(PyThreadState *tstate, PyObject *abs_name)
{
PyObject *modules = tstate->interp->imports.modules;
...
return PyObject_GetItem(modules, abs_name);
}

Frozen modules

Frozen modules are byte-compiled code objects embedded in the interpreter binary. CPython 3.11+ freezes importlib._bootstrap and importlib._bootstrap_external to speed up interpreter startup without touching the file system.

// CPython: Python/import.c:1380 PyImport_ImportFrozenModuleObject
int
PyImport_ImportFrozenModuleObject(PyObject *name)
{
...
p = find_frozen(name, &info);
if (p == NULL) return 0;
...
co = PyMarshal_ReadObjectFromString((const char *)info.data, info.size);
...
}

importlib handoff

At interpreter startup _PyImport_InitImportFunc installs importlib._bootstrap.__import__ as builtins.__import__. From that point all Python-level imports go through importlib.

gopy notes

vm/eval_import.go handles IMPORT_NAME and IMPORT_FROM opcodes. The sys.modules cache lives in the interpreter state. Frozen modules include the stdlibinit registry; path-based loading is not yet implemented.