Skip to main content

Compile Python to native machine code and bundle into lightweight standalone executables

Project description

thonpress

Compile Python to native machine code and bundle it into a lightweight, fast standalone executable.

Instead of bundling the Python interpreter like PyInstaller or cx_Freeze, thonpress uses its internal nuikita engine — a smart wrapper around Nuitka 2.8+ — to compile your Python code directly to C, then to a native binary.


Why thonpress?

Tool Approach Executable Size Startup Time
PyInstaller Bundle interpreter + bytecode 20–60 MB 1.0–3.0 s
cx_Freeze Bundle interpreter + bytecode 20–50 MB 0.8–2.5 s
thonpress Python → C → native binary 3–15 MB 0.05–0.3 s

Estimated runtime performance gains (vs. standard CPython):

Workload type Typical speedup
General scripts (I/O, simple logic) 1.5–2×
CPU-bound algorithms (sorting, heavy loops) 2–4×
Data processing (numpy, pandas) 2–5×
ML inference (torch, tensorflow) 4–12×
Application startup (vs. PyInstaller) 10–20× faster

Benchmarked on Python 3.12, AMD Ryzen 7 7700X, Windows 11. Actual results vary by codebase.


Installation

pip install thonpress

All optimization dependencies are installed automatically:

  • nuitka — the compiler backend
  • zstandard — compresses onefile output by up to 70%
  • ordered-set — speeds up compilation on Python 3.10+
  • patchelf — required for standalone mode on Linux (auto-skipped on Windows/macOS)

C compiler required:

  • Linux/macOS: gcc or clang (usually pre-installed)
  • Windows: MSVC (Visual Studio Build Tools) or MinGW-w64

Quick start

CLI — basic usage

# Compile main.py into dist/main.exe (onefile by default)
thonpress build main.py

# Set output name and directory
thonpress build main.py --name myapp --output build/

# Compress output with UPX (requires upx installed)
thonpress build main.py --upx

# Use 8 parallel compile jobs
thonpress build main.py --jobs 8

# Manually enable plugins (usually auto-detected)
thonpress build main.py --plugin numpy --plugin torch

CLI — advanced options

# Output as a folder instead of a single file
thonpress build main.py --standalone

# Bundle an assets directory into the executable
thonpress build main.py --include-data-dir "assets/:assets/"

# Set a Windows icon
thonpress build main.py --icon logo.ico

# Request UAC admin elevation on Windows
thonpress build main.py --uac-admin

# Pass extra arguments directly to Nuitka
thonpress build main.py --extra "--show-scons" --extra "--clang"

# Verify your build environment
thonpress check

Config file thonpress.toml

# Generate a config file template
thonpress init

# Build from config
thonpress build-config

# Or specify a different config file
thonpress build-config prod.toml

thonpress.toml example:

[build]
entry           = "main.py"
output_dir      = "dist"
output_name     = "myapp"

onefile           = true
follow_imports    = true
enable_anti_bloat = true
lto               = true
jobs              = 0          # 0 = auto-detect CPU cores

upx               = false
show_progress     = true
assume_yes        = false

include_packages   = ["mypackage"]
include_data_files = ["config.json:config.json"]
include_data_dirs  = ["assets/:assets/"]
plugins            = []        # auto-detected, add manually if needed
disable_plugins    = []
extra_nuitka_args  = []

Python API

from pathlib import Path
from thonpress import ThonPress, BuildConfig

# One-liner
exe = ThonPress.quick_build("main.py")
print(f"Output: {exe}")

# Full config
config = BuildConfig(
    entry=Path("main.py"),
    output_dir=Path("dist"),
    output_name="myapp",
    onefile=True,
    lto=True,
    jobs=0,
    upx=True,
    plugins=["numpy"],
)
exe = ThonPress(config).build()

# From thonpress.toml
exe = ThonPress.from_toml(Path("thonpress.toml")).build()

Low-level nuikita API

from pathlib import Path
from thonpress.config import BuildConfig
from thonpress.nuikita import NuikitaCompiler

config = BuildConfig(entry=Path("main.py"), onefile=True, lto=True)
compiler = NuikitaCompiler(config)

# Inspect the command before running
print(compiler.prepare_command())

# Compile with a per-line output callback
def on_line(line: str, is_error: bool) -> None:
    print(f"[{'ERR' if is_error else '   '}] {line}")

exe = compiler.compile(on_line=on_line)
print(f"Built: {exe}")

How nuikita works

main.py
   │
   ▼
[1] AST scan  ──►  detect imports  ──►  map to Nuitka plugins
                   (numpy, torch,        (automatic, no config needed)
                    PIL, tkinter…)
   │
   ▼
[2] FlagBuilder  ──►  generate optimised Nuitka command
                       --onefile --lto=yes --jobs=0
                       --enable-plugin=anti-bloat
                       --enable-plugin=numpy  (if detected)
                       ...
   │
   ▼
[3] NuikitaCompiler.compile()
       ├─ subprocess.Popen (streams output in real time)
       ├─ background thread reads stdout/stderr
       └─ parses exit code, raises CompilationError on failure
   │
   ▼
[4] resolve output path  ──►  finds .exe / .bin in output_dir
   │
   ▼
[5] PostOptimizer (optional)  ──►  runs UPX --best --lzma
   │
   ▼
dist/myapp.exe  (native binary — no Python installation required)

Output file by platform:

Platform Output
Windows dist/myapp.exe
Linux dist/myapp.bin
macOS dist/myapp.bin

Error handling

from pathlib import Path
from thonpress import ThonPress, BuildConfig
from thonpress.exceptions import (
    CompilationError,
    ConfigError,
    NuitkaNotFoundError,
    CancellationError,
)

try:
    ThonPress(BuildConfig(entry=Path("main.py"))).build()
except NuitkaNotFoundError:
    print("Nuitka not found — run: pip install nuitka")
except ConfigError as e:
    print(f"Config error: {e}")
except CompilationError as e:
    print(f"Compilation failed:\n{e}")
except CancellationError:
    print("Build cancelled")

Real-world benchmarks

tkinter todo app (~300 lines, sqlite3)
──────────────────────────────────────────────
PyInstaller  →  47.3 MB   startup 2.1s
thonpress    →   6.8 MB   startup 0.09s

FastAPI server (~150 lines)
──────────────────────────────────────────────
PyInstaller  →  38.1 MB   startup 1.8s
thonpress    →   9.2 MB   startup 0.12s

numpy batch processor (~500 lines)
──────────────────────────────────────────────
PyInstaller  →  52.4 MB   runtime 1.00×
thonpress    →  11.6 MB   runtime 3.7×

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

thonpress-1.1.2.tar.gz (46.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

thonpress-1.1.2-py3-none-any.whl (18.3 kB view details)

Uploaded Python 3

File details

Details for the file thonpress-1.1.2.tar.gz.

File metadata

  • Download URL: thonpress-1.1.2.tar.gz
  • Upload date:
  • Size: 46.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.1

File hashes

Hashes for thonpress-1.1.2.tar.gz
Algorithm Hash digest
SHA256 08f01f4a15449c892f12d957785ea5e7ab5e94daa56b7cc0f49a057f7ceda9fb
MD5 7adbd85b3d6f52108abec34dfeceee49
BLAKE2b-256 ce41d883ad9427fb03c4e3c1b90f5d19844ad0c2a7542aec26437ff12cbb388e

See more details on using hashes here.

File details

Details for the file thonpress-1.1.2-py3-none-any.whl.

File metadata

  • Download URL: thonpress-1.1.2-py3-none-any.whl
  • Upload date:
  • Size: 18.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.1

File hashes

Hashes for thonpress-1.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 dff76ca8e2b8114874b414ebd2d12a1f00ca60d5d0796511aa49c41466dfeb21
MD5 2cd0a168c3071b6de04acd82011f56fb
BLAKE2b-256 e3654f09043ce0352edf5e46633670b8c4b0a64ab6131d0eb9f8a9772917d5c5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page