Objects/moduleobject.c (part 4)
Source:
cpython 3.14 @ ab2d84fe1023/Objects/moduleobject.c
This annotation covers module metadata and multi-phase initialization. See objects_moduleobject3_detail for module.__init__, __getattr__, __dir__, and module.__dict__.
Map
| Lines | Symbol | Role |
|---|---|---|
| 1-80 | module.__repr__ | <module 'name' from 'path'> |
| 81-160 | PyModuleDef | C struct for multi-phase init |
| 161-240 | Multi-phase init | Py_mod_exec slot in PyModuleDef |
| 241-320 | Module __spec__ / __loader__ | Import system metadata attributes |
| 321-500 | sys.modules lifecycle | How modules are installed and unloaded |
Reading
module.__repr__
// CPython: Objects/moduleobject.c:640 module_repr
static PyObject *
module_repr(PyModuleObject *m)
{
PyObject *name = PyObject_GetAttrString((PyObject *)m, "__name__");
PyObject *filename = PyObject_GetAttrString((PyObject *)m, "__file__");
if (filename != NULL) {
return PyUnicode_FromFormat("<module %R from %R>", name, filename);
}
PyErr_Clear();
PyObject *spec = PyObject_GetAttrString((PyObject *)m, "__spec__");
if (spec != NULL) {
return PyObject_CallMethodOneArg(spec, &_Py_ID(_repr_), (PyObject *)m);
}
return PyUnicode_FromFormat("<module %R (built-in)>", name);
}
The repr prefers __file__ (file-based modules). Without a file, it delegates to __spec__._repr_(m) which knows the module's origin (frozen, namespace, etc.). Built-in modules show (built-in).
PyModuleDef multi-phase init
// CPython: Objects/moduleobject.c:120 PyModule_FromDefAndSpec2
PyObject *
PyModule_FromDefAndSpec2(PyModuleDef *def, PyObject *spec, int module_api_version)
{
/* Phase 1: create the module object */
PyObject *mod = PyModule_NewObject(name);
mod->md_def = def;
/* Run Py_mod_create slot if present */
if (def->m_slots) {
for (PyModuleDef_Slot *slot = def->m_slots; slot->slot; slot++) {
if (slot->slot == Py_mod_create)
mod = ((create_fn)slot->value)(spec, def);
}
}
return mod;
}
Multi-phase init (PEP 451) separates module creation (Py_mod_create) from module execution (Py_mod_exec). This allows the module object to be installed in sys.modules before its code runs, enabling circular imports between C extensions and Python modules.
__spec__ attributes
# CPython: Lib/importlib/_bootstrap.py:560 ModuleSpec
class ModuleSpec:
def __init__(self, name, loader, *, origin=None, loader_state=None,
is_package=None):
self.name = name
self.loader = loader
self.origin = origin # Typically __file__
self.submodule_search_locations = [] if is_package else None
# __path__ = submodule_search_locations for packages
module.__spec__ is a ModuleSpec set by the import system. It contains name, loader, origin (file path), and submodule_search_locations (__path__ for packages). After import, the module's __file__, __loader__, __package__, and __path__ are derived from __spec__.
gopy notes
module.__repr__ is objects.ModuleRepr in objects/module.go. Multi-phase init is not yet implemented in gopy. ModuleSpec is objects.ModuleSpec. Module metadata (__spec__, __loader__, __file__) are set in vm/eval_import.go after exec_module completes.