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.0.0.tar.gz (12.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.0.0-py3-none-any.whl (15.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: thonpress-1.0.0.tar.gz
  • Upload date:
  • Size: 12.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.0.0.tar.gz
Algorithm Hash digest
SHA256 c99ea1e511942c975341de9349d9ddb5f18d0a9842755ed8469eebef10ff74bc
MD5 7735b4d2a406330c3be5b276d2deabec
BLAKE2b-256 45e56aaee8c02907b278aadc39cab5695c8bce481e90f65493986e0d97aa38e9

See more details on using hashes here.

File details

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

File metadata

  • Download URL: thonpress-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 15.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.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7e25790501e31c09c7c57cdbc2bf8241ad0df031160a23885d2abeb74e236e42
MD5 acf84102e1655419d83391cb7345adee
BLAKE2b-256 6de10053c4eddfb2551aeb36f407471c1219f3df40faa85558ac1aa203641ca5

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