Python’s importlib.machinery module exposes the concrete classes that implement the standard import machinery. import importlib.machinery. Suffix lists: importlib.machinery.SOURCE_SUFFIXES → [".py"], BYTECODE_SUFFIXES → [".pyc"], EXTENSION_SUFFIXES → [".so", ".pyd", ...]. Loaders: SourceFileLoader(name, path) — reads .py; SourcelessFileLoader(name, path) — reads .pyc; ExtensionFileLoader(name, path) — loads C extension. FileFinder: FileFinder(path, (SourceFileLoader, [".py"]), (SourcelessFileLoader, [".pyc"])) — searches one directory. PathFinder: importlib.machinery.PathFinder.find_spec(name, path) — runs the default sys.path-based search. ModuleSpec: importlib.machinery.ModuleSpec(name, loader, origin=path) — container for all metadata needed to create a module. BuiltinImporter and FrozenImporter — finders for built-in and frozen modules. Register as hook: sys.path_hooks.insert(0, lambda p: FileFinder(p, ...)) — extends .path-based import. Claude Code generates custom file finders, plugin loaders, hot-reload systems, bytecode preloaders, and import-time instrumentation.
CLAUDE.md for importlib.machinery
## importlib.machinery Stack
- Stdlib: import importlib.machinery, importlib.util, sys
- Suffixes: SOURCE_SUFFIXES / BYTECODE_SUFFIXES / EXTENSION_SUFFIXES
- Spec: importlib.machinery.ModuleSpec(name, loader, origin=path)
- Loader: importlib.machinery.SourceFileLoader(name, path)
- .get_source(name) / .get_code(name) / .exec_module(mod)
- Finder: importlib.machinery.FileFinder(path, (Loader, [".py"]))
- Path: importlib.machinery.PathFinder.find_spec(name, path)
- Hook: sys.path_hooks.insert(0, lambda p: FileFinder(p, ...))
importlib.machinery Import Pipeline
# app/importmachutil.py — spec inspect, load file, FileFinder, hot-reload, audit
from __future__ import annotations
import importlib
import importlib.machinery
import importlib.util
import sys
import os
import types
from dataclasses import dataclass, field
from pathlib import Path
# ─────────────────────────────────────────────────────────────────────────────
# 1. ModuleSpec inspection helpers
# ─────────────────────────────────────────────────────────────────────────────
@dataclass
class SpecInfo:
name: str
origin: str | None
loader_type: str
is_package: bool
submod_path: list[str]
def inspect_spec(name: str) -> SpecInfo | None:
"""
Find and inspect the ModuleSpec for a module name without loading it.
Example:
info = inspect_spec("json")
print(info.origin, info.loader_type)
info = inspect_spec("os.path")
"""
try:
spec = importlib.util.find_spec(name)
except (ModuleNotFoundError, ValueError):
return None
if spec is None:
return None
loader_type = type(spec.loader).__name__ if spec.loader else "None"
sub = list(spec.submodule_search_locations) \
if spec.submodule_search_locations else []
return SpecInfo(
name=spec.name,
origin=spec.origin,
loader_type=loader_type,
is_package=bool(spec.submodule_search_locations),
submod_path=sub,
)
def list_installed_suffixes() -> dict[str, list[str]]:
"""
Return the file suffixes recognised by the import machinery.
Example:
suf = list_installed_suffixes()
print(suf["source"]) # [".py"]
"""
return {
"source": importlib.machinery.SOURCE_SUFFIXES,
"bytecode": importlib.machinery.BYTECODE_SUFFIXES,
"extension": importlib.machinery.EXTENSION_SUFFIXES,
}
# ─────────────────────────────────────────────────────────────────────────────
# 2. Load a module from an arbitrary file path
# ─────────────────────────────────────────────────────────────────────────────
def load_source_file(path: "str | Path",
name: str | None = None) -> types.ModuleType:
"""
Load a Python source file as a module using SourceFileLoader.
If name is None, derives the module name from the filename.
Example:
mod = load_source_file("/path/to/plugin.py")
print(mod.__name__, dir(mod))
"""
path = Path(path)
if name is None:
name = path.stem
loader = importlib.machinery.SourceFileLoader(name, str(path))
spec = importlib.machinery.ModuleSpec(name, loader, origin=str(path))
mod = importlib.util.module_from_spec(spec)
sys.modules[name] = mod # register first to support circular imports
try:
loader.exec_module(mod)
except Exception:
sys.modules.pop(name, None)
raise
return mod
def get_module_source(name: str) -> str | None:
"""
Return the source code for an already-importable module, if available.
Example:
src = get_module_source("json")
print(src[:200])
"""
try:
spec = importlib.util.find_spec(name)
except (ModuleNotFoundError, ValueError):
return None
if spec is None or spec.origin is None:
return None
loader = spec.loader
if not isinstance(loader, importlib.machinery.SourceFileLoader):
return None
try:
return loader.get_source(name)
except Exception:
return None
# ─────────────────────────────────────────────────────────────────────────────
# 3. FileFinder — search a directory for Python files
# ─────────────────────────────────────────────────────────────────────────────
def find_module_in_dir(directory: "str | Path",
module_name: str) -> str | None:
"""
Look for module_name in a single directory using FileFinder.
Returns the file path if found, or None.
Example:
path = find_module_in_dir("/usr/lib/python3/dist-packages", "email")
"""
directory = str(directory)
finder = importlib.machinery.FileFinder(
directory,
(importlib.machinery.SourceFileLoader,
importlib.machinery.SOURCE_SUFFIXES),
(importlib.machinery.SourcelessFileLoader,
importlib.machinery.BYTECODE_SUFFIXES),
)
try:
spec = finder.find_spec(module_name)
if spec is not None:
return spec.origin
except Exception:
pass
return None
# ─────────────────────────────────────────────────────────────────────────────
# 4. Hot-reload a module from disk
# ─────────────────────────────────────────────────────────────────────────────
def hot_reload(name: str) -> types.ModuleType | None:
"""
Force a reload of a module from its source file.
Returns the reloaded module, or None if not found.
Example:
import mymodule
# edit mymodule.py on disk …
mymodule = hot_reload("mymodule")
"""
mod = sys.modules.get(name)
if mod is None:
return None
spec = getattr(mod, "__spec__", None)
if spec is None or spec.loader is None:
return None
try:
spec.loader.exec_module(mod)
return mod
except Exception:
return None
# ─────────────────────────────────────────────────────────────────────────────
# 5. Full meta_path loader audit
# ─────────────────────────────────────────────────────────────────────────────
@dataclass
class MetaPathEntry:
index: int
type_name: str
module: str
def audit_meta_path() -> list[MetaPathEntry]:
"""
Return information about every finder on sys.meta_path.
Example:
for entry in audit_meta_path():
print(entry.index, entry.type_name)
"""
entries: list[MetaPathEntry] = []
for i, finder in enumerate(sys.meta_path):
entries.append(MetaPathEntry(
index=i,
type_name=type(finder).__name__,
module=type(finder).__module__,
))
return entries
@dataclass
class PathHookEntry:
index: int
type_name: str
def audit_path_hooks() -> list[PathHookEntry]:
"""Return information about every hook on sys.path_hooks."""
entries: list[PathHookEntry] = []
for i, hook in enumerate(sys.path_hooks):
name = getattr(hook, "__name__",
getattr(hook, "__class__").__name__)
entries.append(PathHookEntry(index=i, type_name=name))
return entries
# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
import tempfile
print("=== importlib.machinery demo ===")
# ── suffixes ──────────────────────────────────────────────────────────────
print("\n--- file suffixes ---")
for k, v in list_installed_suffixes().items():
print(f" {k:10s}: {v}")
# ── inspect_spec ──────────────────────────────────────────────────────────
print("\n--- inspect_spec ---")
for mod_name in ["json", "os.path", "sys", "_json", "email"]:
info = inspect_spec(mod_name)
if info:
print(f" {mod_name:15s} loader={info.loader_type:30s} "
f"pkg={info.is_package}")
# ── load_source_file ──────────────────────────────────────────────────────
print("\n--- load_source_file ---")
with tempfile.NamedTemporaryFile(suffix=".py", mode="w",
delete=False) as tf:
tf.write("ANSWER = 42\ndef greet(name): return f'Hi, {name}!'\n")
tmp_path = tf.name
try:
mod = load_source_file(tmp_path, "demo_mod")
print(f" ANSWER = {mod.ANSWER}")
print(f" greet = {mod.greet('world')!r}")
finally:
os.unlink(tmp_path)
sys.modules.pop("demo_mod", None)
# ── get_module_source ─────────────────────────────────────────────────────
print("\n--- get_module_source (json) ---")
src = get_module_source("json")
if src:
lines = src.splitlines()
print(f" {len(lines)} lines; first non-blank: {next(l for l in lines if l.strip())!r}")
# ── audit meta_path ───────────────────────────────────────────────────────
print("\n--- audit_meta_path ---")
for entry in audit_meta_path():
print(f" [{entry.index}] {entry.type_name}")
# ── audit path_hooks ──────────────────────────────────────────────────────
print("\n--- audit_path_hooks ---")
for entry in audit_path_hooks():
print(f" [{entry.index}] {entry.type_name}")
print("\n=== done ===")
For the importlib.abc stdlib companion — importlib.abc.MetaPathFinder + Loader define the abstract interfaces that importlib.machinery implements concretely — use importlib.abc when writing custom finders and loaders; use importlib.machinery when you need to instantiate, inspect, or extend the standard file-system loaders (SourceFileLoader, FileFinder, ExtensionFileLoader). For the importlib.util stdlib companion — importlib.util.find_spec(name) calls PathFinder and returns the ModuleSpec without loading the module; importlib.util.module_from_spec(spec) creates an empty module object from a spec — use importlib.util for safe high-level find-without-load and module creation; use importlib.machinery when you need direct access to the loader classes themselves to set up FileFinder hooks or read source from a loader. The Claude Skills 360 bundle includes importlib.machinery skill sets covering SpecInfo/inspect_spec() metadata reader, list_installed_suffixes() suffix table, load_source_file() path-based loader, get_module_source() source reader, find_module_in_dir() FileFinder wrapper, hot_reload() exec_module reloader, and MetaPathEntry/PathHookEntry/audit_meta_path()/audit_path_hooks() auditors. Start with the free tier to try import machinery patterns and importlib.machinery pipeline code generation.