An experimental CPython bytecode compiler, written in Rust.
Warning
Serc is experimental. All code changes, PR summaries, and additional documentation were authored entirely by GPT-6 Astra in Codex. Use at your own risk.
- Compile Python source to CPython
.pycfiles without a CPython installation. - Target Python 3.12, 3.13, 3.14, and 3.15 with a single executable.
- Check source files and recursively compile packages from the command line.
- Embed the compiler via the Rust library.
Serc produces byte-for-byte identical output on an extensive corpus of real-world Python code, including Django, Airflow, and Transformers, >40% faster than CPython's built-in compiler:
| Project | Serc | CPython 3.14.5 compileall |
Speedup |
|---|---|---|---|
| NumPy 2.4.6 (505 files) | 1.194 s ± 0.023 s | 1.739 s ± 0.060 s | 1.46× |
But Serc is also experimental! And so may emit incorrect bytecode in some cases.
Install from crates.io with Rust 1.96 or later:
cargo install serc-cli --lockedGiven hello.py:
def greet(name):
return f"Hello, {name}!"Compile it to bytecode, emitted at __pycache__/hello.cpython-314.pyc:
serc compile hello.pyPass a directory to compile its Python files recursively, or use --check to
compile without writing cache files:
serc compile path/to/package
serc compile --check path/to/packageCompilation uses the available CPUs by default. Use --jobs (or -j) to set a
limit, including --jobs 1 for serial compilation. You can also set the default
with RAYON_NUM_THREADS:
serc compile --jobs 4 path/to/packageUse --files-from - to read a list of files from standard input. Paths are
newline-delimited by default; --null accepts NUL-delimited paths, including
filenames that contain newlines:
find path/to/package -type f -name '*.py' -print0 | serc compile --files-from - --nullThe list selects individual files without scanning directories. On Unix, paths retain their original bytes; on Windows, the list must use UTF-8.
Current .pyc files are left untouched by default. We compare the target
bytecode format and invalidation mode, then the source's timestamp and size or
its content hash. Pass -f or --force to rebuild every file, including after
changing the compiler or native build profile. --check always compiles the
sources without writing bytecode. Existing bytecode destinations must be regular
files; compilation rejects symlinks and special files, including with --force.
For integrations, --output-format json reports the numbers of compiled and
skipped files:
serc compile --files-from - --null --output-format jsonSerc emits Python 3.14-compatible bytecode by default, but supports target
selection with --python-version. For example, to emit Python 3.15 bytecode:
serc compile --python-version 3.15 path/to/packageSerc supports the following CPython minor versions:
| Target | Pinned CPython release |
|---|---|
3.12 |
3.12.14 |
3.13 |
3.13.15 |
3.14 |
3.14.5 |
3.15 |
3.15.0rc2 |
Each target writes its own cache tag and bytecode magic number, so the four
versions can coexist under __pycache__.
Use -O to remove assertions and set __debug__ to false, matching Python's
-O mode. Use -OO to additionally remove module, class, and function
docstrings:
serc compile -O hello.py
serc compile -OO hello.pyYou can also select the level explicitly with --optimize 0, --optimize 1, or
--optimize 2. Level 0 is the default. Optimized caches use Python's naming
convention, such as __pycache__/hello.cpython-314.opt-1.pyc and
__pycache__/hello.cpython-314.opt-2.pyc, so all three levels can coexist.
Add Serc to your Cargo.toml:
[dependencies]
serc = "0.1.0"Compile Python source and serialize the resulting code object in CPython's marshal format:
let module = serc::compile("print('Hello, world!')\n", "hello.py").unwrap();
let marshaled = module.marshal();Compilation defaults to Python 3.14. See the
library guide for selecting another Python
version and generating .pyc files.
Serc is licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or https://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Serc by you, as defined in the Apache-2.0 license, shall be dually licensed as above, without any additional terms or conditions.