Skip to main content

Python/frozen.c (part 2)

Source:

cpython 3.14 @ ab2d84fe1023/Python/frozen.c

This annotation covers the extended set of frozen modules added in Python 3.11-3.14. See python_frozen_detail for _PyImport_IsFrozenModule, _Py_FrozenBootstrap, and how frozen code is embedded.

Map

LinesSymbolRole
1-50Frozen aliasesimportlib._bootstrap_external alias resolution
51-100_PyImport_FrozenAliasesTable mapping alias names to canonical names
101-200Standard frozen set_collections_abc, _abc, posixpath, ntpath, genericpath
201-250_Py_FrozenStdlibFull stdlib frozen set (3.11+ when --enable-frozen-modules)

Reading

Why these modules are frozen

// CPython: Python/frozen.c:12 comment
/* These modules are frozen into the interpreter to allow the import system
to start without needing a working file system. They must be loadable
before the path-based finder is available.

Bootstrap order:
1. _frozen_importlib (importlib._bootstrap)
2. _frozen_importlib_external (importlib._bootstrap_external)
3. zipimport
4. _collections_abc, _abc (needed by importlib internals)
5. posixpath / ntpath (needed for path manipulation in bootstrap)
*/

_PyImport_FrozenAliases

// CPython: Python/frozen.c:55 _PyImport_FrozenAliases
static const struct _frozen _PyImport_FrozenAliases[] = {
/* Bootstrap aliases */
{"_frozen_importlib", NULL, 0, 0, "_bootstrap"},
{"_frozen_importlib_external", NULL, 0, 0, "_bootstrap_external"},
/* Stdlib aliases (3.11+) */
{"importlib._bootstrap", M__importlib__bootstrap,
sizeof(M__importlib__bootstrap), 0},
{"importlib._bootstrap_external", M__importlib__bootstrap_external,
sizeof(M__importlib__bootstrap_external), 0},
{0, 0, 0, 0} /* sentinel */
};

Alias entries have a NULL code pointer. The import machinery resolves them to the canonical name and finds the actual frozen data there.

Standard frozen modules (3.11+)

// CPython: Python/frozen.c:130 _PyImport_FrozenStdlib
/* When --enable-frozen-modules is used at build time, additional stdlib
modules are compiled into frozen bytecode. This speeds up startup
by avoiding disk reads for commonly-imported modules. */
static const struct _frozen _PyImport_FrozenStdlib[] = {
/* abc, codecs, collections, functools, io, os, ... */
{"abc", M_abc, sizeof(M_abc), 0},
{"codecs", M_codecs, sizeof(M_codecs), 0},
{"os", M_os, sizeof(M_os), 0},
...
{0, 0, 0, 0}
};

How frozen bytecode is generated

# CPython Makefile:
# Python/frozen_modules/*.h are generated by:
# python Tools/freeze/freeze.py Lib/importlib/_bootstrap.py
# python Tools/build/freeze_modules.py
# Each .h file contains:
# static unsigned char M_importlib__bootstrap[] = { ... bytecode bytes ... };

The bytecode is stored as a C array literal. At startup, _PyImport_FindFrozenObject finds the entry by name and returns a PyBytesObject wrapping the array (no copy needed).

gopy notes

gopy embeds the same frozen modules at build time using Go's //go:embed directive in stdlibinit/frozen.go. The bytecode arrays are in stdlib/frozen/ as Go []byte variables. _PyImport_IsFrozenModule is vm.IsFrozenModule in vm/eval_import.go. Frozen aliases are resolved in the same function.