Skip to content
astral-shPublic

About

An experimental CPython bytecode compiler, written in Rust.

Resources

Code of conduct

Security policy

Stars

8 stars

Watchers

0 watching

Forks

Latest commit

 

History

1,250 Commits

Folders and files

Serc

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.

Highlights

  • Compile Python source to CPython .pyc files 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.

Installation

Install from crates.io with Rust 1.96 or later:

cargo install serc-cli --locked

Getting started

Given hello.py:

def greet(name):
    return f"Hello, {name}!"

Compile it to bytecode, emitted at __pycache__/hello.cpython-314.pyc:

serc compile hello.py

Pass 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/package

Compilation 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/package

Use --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 - --null

The 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 json

Python version

Serc 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/package

Serc 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__.

Optimization

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.py

You 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.

Rust library

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.

License

Serc is licensed under either of

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.

About

An experimental CPython bytecode compiler, written in Rust.

Resources

Code of conduct

Security policy

Stars

8 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages