Py2Native Compile custom Python into native machine code to protect proprietary code

← All posts

2026-08-26

Py2Native Tutorial: Compile Your First Python Binary in Minutes

Py2Native Tutorial: Compile Your First Python Binary in Minutes
python compiler cython code protection open source

Py2Native Tutorial: Compile Your First Python Binary in Minutes

If you ship Python software, you already know the uncomfortable truth: your .py files are readable source code. Customers, partners, and competitors can open them, copy your logic, or patch out your license checks. But what if you could protect that code without learning Cython, without writing C extensions, and without maintaining a fragile build pipeline?

That is exactly what this Py2Native tutorial answers. You write plain Python. Py2Native compiles it into native machine code. You ship a binary instead of readable source.

What is Py2Native and Why Use It?

Py2Native is a zero-config Python-to-native compiler. It takes your custom Python modules, transpiles them through Cython under the hood, compiles the result with your platform C compiler, and links it into a native shared library or executable.

The important part is what you don’t do:

  • You don’t write Cython syntax.
  • You don’t create .pyx or .pxd files by hand.
  • You don’t run a manual cythonize step.
  • You don’t write C extensions or wrestle with build flags.

The raw alternative exists: you could learn Cython’s syntax, manage .pyx files, generate C, compile it, and link it yourself. That is the hard way. Py2Native automates all of it behind a single command:

uv run py2native build main.py app/*.py

A useful mental model is a translator at a patent office. You hand over your working notes in plain English. The translator produces a finished, sealed document that contains the invention, but not every draft, edit, or note you made along the way. Py2Native converts editable Python source into compiled machine code: the behavior survives, but the readable source does not need to ship with the product.

Third-party libraries such as Requests or NumPy are left as Python source and work as-is. Py2Native compiles only your code. That means you get source protection for proprietary logic while keeping normal Python environment behavior for dependencies.

How Py2Native Works Under the Hood

The pipeline is short and fully automated:

  1. Glob sources — Py2Native expands the source patterns you provide.
  2. Plugin dispatch — core and optional Pro plugins extend the build.
  3. Cython transpilation — Py2Native generates a bootstrap.pyx, converts your Python to C, and hides the details.
  4. C compilation — your platform compiler builds object files from the generated C.
  5. Linking — Py2Native links the result into an executable or shared library.
  6. Optional output — --wheel creates a PEP 427 wheel, while --embed creates a uv-managed deployment directory.

The plugin system is how Py2Native handles platform-specific work. Windows, Linux, and macOS plugins supply compiler flags, linker arguments, and output naming rules. The commercial Pro plugin adds JWT license verification, key generation, and signing commands.

For license verification, Py2Native Pro uses elliptic curve cryptography. Only the public key is stored in the executable. The private key never ships. Signature verification is handled by compiled code inside Py2Native, not by third-party libraries.

Step-by-Step: Compile Your First Python Script

Prerequisites

Before you start, make sure you have:

  • CPython 3.11–3.15, including free-threaded 3.14t and 3.15t.
  • A platform C compiler: MSVC on Windows, GCC on Linux, or Clang on macOS.
  • uv installed. Py2Native is always run as uv run py2native, so uv fetches the required packages for the command.
  • Internet access, because uv downloads Python distributions and libraries as needed.

Supported platforms are Windows 8+, manylinux2014/musl Linux, and macOS on x86-64 or ARM64 CPUs.

Create a simple script

Start with a small Python file:

# hello.py
def main():
    print("Hello from native code!")

if __name__ == "__main__":
    main()

Compile it

Run the build command. The first hello.py is the executable entry point; the second is the source list. For a single-file project, the same file serves both roles:

uv run py2native build hello.py hello.py

When the build completes, Py2Native produces a native binary named after the main module — for example, hello on Linux/macOS or hello.exe on Windows. The original .py file is not required at runtime.

Optional output flags

Py2Native can produce more than a bare executable. Use --embed to create a uv-managed deployment directory:

uv run py2native build --embed deploy hello.py hello.py

Use --wheel to create a PEP 427 wheel containing the compiled .pyd or .so:

uv run py2native build --wheel dist hello.py hello.py

Use --library to create a shared library instead of an executable. In library mode, the generated wheel contains a single compiled shared library, an __init__.py that redirects imports through a meta-path finder, and an __main__.py so the package can be run with python -m:

uv run py2native build --library --wheel dist hello.py hello.py

For a larger project, pass the main module followed by a glob for the source files:

uv run py2native build main.py src/*.py

Adding License Verification with Pro Plugin

Community edition is MIT-licensed and gives you full compilation. Pro adds commercial licensing controls through py2nativepro.

The Pro plugin works like this:

  1. Generate an EC P-256 keypair.
  2. Sign a license token as a JWT.
  3. Embed the public key and verification code into your binary.
  4. Require a valid license at runtime.

1. Generate the keypair

uv run py2native keygen private.pem public.pem

This creates private.pem and public.pem. Keep the private key safe on your build machine. The public key is safe to embed.

2. Sign a license

uv run py2native sign --private private.pem '{"sub":"customer-123","exp":"2027-08-26"}' license.dat

The license.dat file now contains a signed JWT for that customer.

3. Inspect the license

You can display the JWT claims and optionally verify the signature against the public key:

uv run py2native show --public public.pem license.dat

4. Call the verifier from your code

For Pro builds, include the .pxd file supplied by the Pro plugin. This file declares the license verification call that the build injects into your executable. The exact module and function name come from the Pro plugin; the example below shows the shape of the call, not a fixed API:

# main.py
def main():
    with open("license.dat", "r") as f:
        token = f.read().strip()

    # verify_license is declared in the Pro plugin's .pxd file and
    # compiled directly into this executable. If the token is invalid,
    # the process stops before your proprietary logic runs.
    verify_license(token)

    print("License valid — running protected code")

The Pro build bakes the signature verification code and the public key into the executable. You do not ship the private key, and you do not depend on an external license server.

5. Build with a required license

Use the --license and --public flags to link the verifier into the binary:

uv run py2native build --license license.dat --public public.pem main.py main.py

This keeps licensing self-contained: the binary checks the signed token locally, with the public key already embedded.

Common Misconceptions and Best Practices

Py2Native makes source protection practical, but it is not magic.

Native code is not 100% tamper-proof. A determined attacker can still reverse engineer a compiled binary. Py2Native raises the cost and effort significantly compared with shipping .py files, but it does not make reverse engineering impossible.

Monkey-patching is still possible. Because third-party libraries remain as Python source, an end user can patch those dependencies. Your compiled modules are protected, but the surrounding Python environment is not.

LGPL libraries remain replaceable. That is a compliance feature, not a loophole. If your application includes LGPL-licensed dependencies, end users retain the right to replace those libraries. Py2Native does not prevent that.

Best practices:

  • Put sensitive algorithms, business rules, and license checks in compiled modules.
  • Keep third-party dependencies as normal Python packages so they remain easy to update.
  • Use Pro license verification for commercial products that need local JWT checks.
  • Avoid duplicate module names across source files — Py2Native does not support modules with identical names.
  • For a deeper security discussion, see Enterprise Python Code Protection: Why Native Compilation Matters.

FAQ

Do I need to know Cython to use Py2Native?

No. Py2Native hides Cython completely. You write plain Python and run a single command; Py2Native handles the Cython transpilation and C compilation automatically.

Can I compile Python code that uses third-party libraries like NumPy or Requests?

Yes. Third-party libraries are left as Python source and work as-is. Py2Native compiles only your custom Python code into native machine code, so dependencies continue to function normally.

Is Py2Native free to use?

The core compiler is open source under the MIT license and free to use. A commercial Pro plugin adds license verification features such as JWT signing, verification, and key management for protecting commercial products.

What platforms does Py2Native support?

Py2Native supports Windows 8+, manylinux2014/musl Linux, and macOS on x86-64 or ARM64 CPUs. It requires CPython 3.11–3.15 and a platform C compiler: MSVC on Windows, GCC on Linux, or Clang on macOS.

Conclusion

Py2Native turns the usual Python source-protection problem into a one-command workflow. You write plain Python, run uv run py2native build, and get a native binary. No Cython syntax, no manual build steps, no hand-written C extensions.

Start with the open-source Community edition to compile your first script. If you sell software and need local license verification, evaluate the Pro plugin with its EC-signed JWT workflow and embedded public-key checks. Keep your proprietary logic compiled, leave third-party libraries as Python source, and ship with a much smaller source-code footprint.

Related posts

EU label: AI-generated content