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.1.tar.gz (36.7 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.1-py3-none-any.whl (18.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: thonpress-1.1.1.tar.gz
  • Upload date:
  • Size: 36.7 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.1.tar.gz
Algorithm Hash digest
SHA256 dfc6cfe00f98eaf36c9f9ea80a65e328db85a856cfa69df063c831b0b56ed230
MD5 9c42308cd32cfe5f0f43a2a107cb38ab
BLAKE2b-256 fbe3458eae71912d2f90f8d1306d35668ed1e6d0986853c5655b15a3bdadf13b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: thonpress-1.1.1-py3-none-any.whl
  • Upload date:
  • Size: 18.2 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c4e6b8f22615b0a115c9c105a71f18310b7a41ebccc327c4101ba9bffc0f9a3c
MD5 db23d731aefbf53d42193de0c4e494df
BLAKE2b-256 5fe551cf1a6fc3c7e34eecac76ef681135bfbd40bb4a0e1ac3a92b735ce4b05c

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