Lib/py_compile.py
cpython 3.14 @ ab2d84fe1023/Lib/py_compile.py
py_compile provides a single public function, compile(), that reads a Python source file, compiles it to bytecode, and writes the result as a .pyc file under __pycache__. It is the minimal public surface over the same machinery that importlib uses when it auto-compiles modules on import.
The module defines PycInvalidationMode, an IntEnum with three members: TIMESTAMP (the historical default), CHECKED_HASH, and UNCHECKED_HASH. The mode controls what is written into the .pyc header so that the import system can decide whether cached bytecode is still valid. It also exposes PyCompileError, a thin exception wrapper that formats a friendly message pointing at the offending file and line.
The compile() function is the workhorse. It resolves source and cache paths, reads the source bytes, delegates compilation to importlib.util.source_to_code, then calls into importlib._bootstrap_external to stamp the header and write the .pyc atomically. The quiet parameter suppresses PyCompileError and makes the function return a status integer instead of raising.
Map
| Lines | Symbol | Role | gopy |
|---|---|---|---|
| 1-30 | module header | Imports, __all__, docstring | - |
| 31-60 | PyCompileError | Exception with formatted message and underlying SyntaxError | - |
| 61-100 | PycInvalidationMode | IntEnum with TIMESTAMP, CHECKED_HASH, UNCHECKED_HASH | - |
| 101-140 | compile() signature + path setup | Argument defaulting, cfile resolution via importlib.util.cache_from_source | - |
| 141-180 | compile() source read | Opens source with io.open_code, reads bytes, handles OSError | - |
| 181-230 | compile() compilation | Calls importlib.util.source_to_code, catches SyntaxError, wraps in PyCompileError | - |
| 231-265 | compile() write | Calls _bootstrap_external._write_atomic with magic + header + marshalled code | - |
| 266-290 | main() / __main__ block | CLI: iterates sys.argv[1:], calls compile(), prints errors | - |
Reading
PyCompileError (lines 31 to 60)
cpython 3.14 @ ab2d84fe1023/Lib/py_compile.py#L31-60
PyCompileError wraps any exception raised during compilation and produces a human-readable message that includes the filename and, when the underlying error is a SyntaxError, the line number. The exc_value attribute preserves the original exception for programmatic inspection.
class PyCompileError(Exception):
def __init__(self, exc_type, exc_value, file, msg=''):
self.exc_type_name = exc_type.__name__
self.exc_value = exc_value
self.file = file
# builds self.msg from the above, including lineno when available
super().__init__(msg or self.msg)
PycInvalidationMode enum (lines 61 to 100)
cpython 3.14 @ ab2d84fe1023/Lib/py_compile.py#L61-100
The three members map directly to the .pyc header flags defined in importlib._bootstrap_external. TIMESTAMP stores the source mtime and size. CHECKED_HASH stores a hash that the import system verifies on every load. UNCHECKED_HASH stores a hash but the import system trusts it without re-checking.
class PycInvalidationMode(enum.IntEnum):
TIMESTAMP = 1
CHECKED_HASH = 2
UNCHECKED_HASH = 3
Path resolution in compile() (lines 101 to 140)
cpython 3.14 @ ab2d84fe1023/Lib/py_compile.py#L101-140
When cfile is omitted, the cache path is derived from the source path using importlib.util.cache_from_source, which inserts the __pycache__ subdirectory and appends the magic-number suffix. The dfile parameter (display filename) lets callers embed a different path in tracebacks, for example when compiling from a temporary copy.
if cfile is None:
if optimize >= 0:
cfile = importlib.util.cache_from_source(file, optimization=optimize or '')
else:
cfile = importlib.util.cache_from_source(file)
Compilation and error wrapping (lines 181 to 230)
cpython 3.14 @ ab2d84fe1023/Lib/py_compile.py#L181-230
importlib.util.source_to_code is a thin wrapper around the built-in compile(). Any SyntaxError (or subclass) it raises is caught and re-raised as PyCompileError. With quiet >= 2 the error is swallowed entirely and the function returns ''.
try:
code = loader.source_to_code(source_bytes, dfile or file,
_optimize=optimize)
except SyntaxError as err:
py_exc = PyCompileError(err.__class__, err, dfile or file)
if quiet < 2:
raise py_exc
return ''
Writing the .pyc file (lines 231 to 265)
cpython 3.14 @ ab2d84fe1023/Lib/py_compile.py#L231-265
The header is assembled by _bootstrap_external helpers: magic number (4 bytes), flags word, then either mtime+size or hash depending on the invalidation mode. The marshalled code object follows. _write_atomic writes to a temp file and renames, so a concurrent reader never sees a partial .pyc.
bytecode = importlib._bootstrap_external._code_to_timestamp_pyc(
code, source_mtime, source_size)
importlib._bootstrap_external._write_atomic(cfile, bytecode, mode)
gopy mirror
Not yet ported.