compileall Module¶
The compileall module compiles all Python source files in a directory tree to bytecode (.pyc files).
Complexity Reference¶
| Operation | Time | Space | Notes |
|---|---|---|---|
compile_dir() |
O(E + B) | O(E + M) | E = every directory entry examined, not just .py files; B = source bytes compiled; M = the largest single file's compilation working set, which dominates. Measured on CPython 3.11, one Linux machine, tmpfs - illustrative: 5000 non-Python files added to 20 modules made it 10.9x slower, 200 ten-line files cost about nine times 10 two-hundred-line files, and one 1.8 MB module peaked at 232 MB |
compile_file() |
O(m) | O(m) | m = file size; one file |
workers=N |
- | O(E + N*M) | Each process holds its own copy of M, so peak memory scales with the worker count |
compile_path() |
O(E + B) | O(E + M) | Same walk, over the entries of each sys.path directory |
main() |
O(E + B) | O(E + M) | CLI entrypoint |
Batch Compiling Python Files¶
Compile Directory¶
import compileall
import tempfile
from pathlib import Path
tree = Path(tempfile.mkdtemp())
(tree / 'example.py').write_text('value = 1\n')
# Compile directory tree - O(E + B)
compileall.compile_dir(tree)
# With options
compileall.compile_dir(
tree,
force=True, # Recompile all
quiet=0 # Show progress
)
# workers=N compiles files in parallel (workers=0 uses one per CPU)
compileall.compile_dir(tree, workers=4, quiet=1)
# Or from command line:
# python -m compileall /path/to/code
The return value only reports compilation failures
compile_dir() returns False when a file fails to compile, and True
otherwise - including when it could not read the directory at all. A path
that does not exist, or that is a file rather than a directory, is
reported as success.
import compileall
import tempfile
from pathlib import Path
tree = Path(tempfile.mkdtemp())
(tree / 'broken.py').write_text('def (\n')
compileall.compile_dir(tree, quiet=2) # False - a real failure
compileall.compile_dir(tree / 'nowhere', quiet=2) # True, despite listing nothing
compileall.compile_dir(tree / 'broken.py', quiet=2) # True, and it is not a directory
# So check the path yourself before trusting the result
def compile_tree(path):
if not path.is_dir():
raise NotADirectoryError(path)
return compileall.compile_dir(path, quiet=2)
print(compile_tree(tree)) # False - broken.py is still in there
Compile Single File¶
import py_compile
import tempfile
from pathlib import Path
source = Path(tempfile.mkdtemp()) / 'myfile.py'
source.write_text('value = 1\n')
# Compile one file - O(m) in the file's size
py_compile.compile(source)
# A missing file raises rather than returning None - doraise only controls
# what happens to compilation errors, not to reading the source
try:
py_compile.compile(source.with_name('absent.py'))
except FileNotFoundError as error:
print(f'no such source: {error.filename}')