Skip to main content

compilecode

compilecode compiles a project's Python modules to native .so extension modules with Nuitka. The original .py sources and bytecode are removed afterwards. There is no key and no runtime decryption: the compiled modules are imported directly by Python.

Usage

Drop-in one-liner, run from the project root:

python -m compilecode .

Or, after installing the package (pip install -e .):

compilecode path/to/project

Options:

  • --strip-docstrings removes docstrings from the compiled modules.
  • --jobs N / -j N compiles that many modules in parallel. Each module is an independent Nuitka subprocess, so compiling a tree is roughly N× faster on an N-core box. The default is min(4, CPU count) — capped because every job is a Nuitka + C-compiler process and uses real RAM. Pass --jobs 1 to force serial compilation.
  • --nuitka-jobs N caps how many C-compiler (cc1) jobs Nuitka forks per module. Nuitka's default is all cores, and on large modules each cc1 can use hundreds of MB — the usual cause of an out-of-memory kill. Lower this to cap peak memory.
  • --low-memory is the one switch for a small build host (~4 GB): it compiles one module at a time, with one cc1 job, and turns on Nuitka's own low-memory mode. Slower, but it keeps the build from being OOM-killed. Combine it with a .compilecodeignore (below) that skips migrations, settings, and tests to cut the load further.

Running out of memory? A big Django/FastAPI project compiled on a small host can exhaust RAM: Nuitka forks several cc1 C-compilers (hundreds of MB each) per large module, and --jobs > 1 multiplies that across modules. If the build grinds for a long time and then dies, reach for --low-memory, give the builder more RAM, or skip non-proprietary files via .compilecodeignore.

The exit code is 0 on success and 1 if any module failed to compile or its source was not fully removed.

Drop-in swap (Docker)

The reference references/Dockerfile keeps the same compileit.sh one-liner against $DOCKERHOME, so existing setups swap in without other changes. The line now compiles the project to .so modules with Nuitka instead of encrypting it. No key is generated or shipped in the image, so there is nothing to store or rotate. The builder stage installs nuitka, and the runtime stage no longer installs git, vim or dos2unix.

Ignoring files

Place a .compilecodeignore file in the project root to override which files are compiled. It holds one pattern per line; blank lines and lines starting with # are ignored. A pattern matches files that are left as plain Python. A line starting with ! forces a file to be compiled even if another rule would skip it.

Packaging

compileit.sh ships inside the installed compilecode/ package. It runs python -m compilecode and honours the PYTHON environment variable to pick the interpreter.

Releasing to PyPI / TestPyPI

release.sh versions, builds, and publishes the package. Everything runs inside the docker compose test container — you only need Docker on the host; build, twine, and setuptools_scm are never installed locally.

The version lives in git tags (via setuptools_scm): you never edit a version by hand. release.sh computes the next one, tags the commit, builds the sdist + wheel, uploads, and pushes the commit and tag back.

./release.sh <testpypi|pypi> [version] [options]

Version selection (pick at most one; default is a patch bump):

You pass Version used Example
(nothing) patch bump of the latest tag 0.1.3 → 0.1.4
(nothing), but HEAD is already on a tag that tag is reused (so testpypi → pypi publishes the same version) 0.1.3
--minor minor bump, patch reset 0.1.3 → 0.2.0
--major major bump, minor+patch reset 0.1.3 → 1.0.0
--version X.Y.Z exactly that 2.5.1

Options

  • --dry-run — compute the version, build, and twine check only. Makes no git changes, uploads nothing, pushes nothing. Run this first.
  • --no-push — publish but skip git push --follow-tags.

Authentication (only needed for a real upload). Either works:

  1. A .pypirc with [pypi] / [testpypi] sections (the default when no token env is set). It is searched as $PYPIRC, then ./.pypirc, then ~/.pypirc, mounted read-only into the container, and used via twine upload --repository <target>. The [testpypi] section must include its repository = https://test.pypi.org/legacy/ line:

    [pypi]
      username = __token__
      password = pypi-AgEI...
    [testpypi]
      repository = https://test.pypi.org/legacy/
      username = __token__
      password = pypi-AgEI...
    
  2. export TWINE_API_TOKEN="pypi-...." — a single token that takes precedence over .pypirc (matches twine's own env-over-file rule). Handy for CI.

Create tokens at https://pypi.org/manage/account/token/ (or test.pypi.org).

First release

./release.sh testpypi --version 0.1.0 --dry-run   # rehearse, no side effects
./release.sh testpypi --version 0.1.0             # tag v0.1.0, publish to TestPyPI
./release.sh pypi     --version 0.1.0             # same version → real PyPI

Routine release after merging new commits:

./release.sh testpypi --dry-run    # shows the next patch, e.g. 0.1.1
./release.sh testpypi              # tag v0.1.1, publish to TestPyPI, push
./release.sh pypi                  # HEAD on v0.1.1 → reuse → publish to PyPI

Verify a TestPyPI upload installs (its deps still come from real PyPI):

pip install --index-url https://test.pypi.org/simple/ \
    --extra-index-url https://pypi.org/simple/ compilecode

Try it end-to-end (smoke test)

references/examples/sample-project/ is a small app that exercises the tricky cases (nested relative imports, a dataclass, a data file, an entry script). Its smoke.sh builds the real two-stage Docker image — compile under full python:3.13, run under python:3.13-slim — and asserts the compiled app runs while its .py sources are gone:

./references/examples/sample-project/smoke.sh

Metadata

Release files for compilecode 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for compilecode 0.1.1
File Size Uploaded Provenance
compilecode-0.1.1.tar.gz 12.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for compilecode 0.1.1
File Interpreter ABI Platform
compilecode-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 24.3 kB

Release files / compilecode-0.1.1.tar.gz

Download URL compilecode-0.1.1.tar.gz
Size 12.7 kB
Tags Source
SHA-256 checksum
How to use checksums
15cef8ec7138396340285f4530b4a9200a51c7034ba5cbff0955e249d4108a95
BLAKE2b-256 checksum
How to use checksums
6e2dbdd5afc25994c2dd1e22343c892650140e42dea5a5f63169cd4c501a2460
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.18

Release files / compilecode-0.1.1-py3-none-any.whl

Download URL compilecode-0.1.1-py3-none-any.whl
Size 11.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f3985423d7f85087f345ea92b5769936c176e18155cab0d5f6a6c2c0c0061504
BLAKE2b-256 checksum
How to use checksums
9f6b3c56894af284a3b9e8b0cf0810fe811b2b35c5b7da450bc849210eb07253
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.18

Security for compilecode 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page