an attention-grabbing library the opposite day that I hadn’t heard of earlier than.
PythoC is a Area-Particular Language (DSL) compiler that enables builders to put in writing C packages utilizing commonplace Python syntax. It takes a statically-typed subset of Python code and compiles it instantly all the way down to native machine code by way of LLVM IR (Low Degree Digital Machine Intermediate Illustration).
LLVM IR is a platform-independent code format used internally by the LLVM compiler framework. Compilers translate supply code into LLVM IR first, after which LLVM turns that IR into optimised machine code for particular CPUs (x86, ARM, and many others.).
A core design philosophy of PythoC is: C-equivalent runtime + Python-powered compile-time, and it has the next nearly distinctive promoting factors.
1. Creates Standalone Native Executables
Not like instruments comparable to Cython, that are primarily used to create C-extensions to hurry up present Python scripts, PythoC can generate utterly impartial, standalone C-style executables. As soon as compiled, the ensuing binary doesn’t require the Python interpreter or a rubbish collector to run.
2. Has Low-Degree Management with Python Syntax
PythoC mirrors C’s capabilities however wraps them in Python’s cleaner syntax. To realize this, it makes use of machine-native kind hints as a substitute of Python’s commonplace dynamic sorts.
- Primitives: i32, i8, f64, and many others.
- Reminiscence constructions: Pointers (ptr[T]), arrays (array[T, N]), and structs (created by adorning commonplace Python courses).
- Handbook Reminiscence Administration: As a result of it doesn’t use a rubbish collector by default, reminiscence administration is specific, identical to in C. Nonetheless, it presents trendy, elective security checks, comparable to linear sorts (which make sure that each allocation is explicitly deallocated to forestall leaks) and refinement sorts (to implement compile-time validation checks).
Python as a Metaprogramming Engine
Considered one of PythoC’s strongest options is its dealing with of the compilation step. As a result of the compile-time surroundings is simply Python, you need to use commonplace Python logic to generate, manipulate, and specialise your PythoC code earlier than it will get compiled all the way down to LLVM. This provides you extremely versatile compile-time code-generation capabilities (just like C++ templates however pushed by pure Python).
It sounds promising, however does the truth reside as much as the hype? Okay, let’s see this library in motion. Putting in it’s straightforward, like most Python libraries its only a pip set up like this:
pip set up pythoc
However it’s most likely higher to arrange a correct improvement surroundings the place you possibly can silo your completely different tasks. In my instance, I’m utilizing the UV utility, however use whichever technique you’re most comfy with. Sort within the following instructions into your command line terminal.
C:Usersthomaprojects> cd tasks
C:Usersthomaprojects> uv init pythoc_test
C:Usersthomaprojects> cd pythoc_test
C:Usersthomaprojectspythoc_test> uv venv --python 3.12
C:Usersthomaprojectspythoc_test> .venvScriptsactivate
(pythoc_test) C:Usersthomaprojectspythoc_test> uv pip set up pythoc
A Easy Instance
To make use of PythoC, you outline features utilizing particular machine sorts and mark them with PythoC’s compile decorator. There are two primary methods to run your PythoC code. You’ll be able to name the compiled library instantly from Python like this,
from pythoc import compile, i32
@compile
def add(x: i32, y: i32) -> i32:
return x + y
# Can compile to native code
@compile
def primary() -> i32:
return add(10, 20)
# Name the compiled dynamic library from Python instantly
end result = primary()
print(end result)
Then run it like this.
(pythoc_test) C:Usersthomaprojectspythoc_test>python test1.py
30
Or you possibly can create a standalone executable you could run independently from Python. To do this, use code like this.
from pythoc import compile, i32
@compile
def add(x: i32, y: i32) -> i32:
print(x + y)
return x + y
# Can compile to native code
@compile
def primary() -> i32:
return add(10, 20)
if __name__ == "__main__":
from pythoc import compile_to_executable
compile_to_executable()
We run it the identical method.
(pythoc_test) C:Usersthomaprojectspythoc_test>python test4.py
Efficiently compiled to executable: buildtest4.exe
Linked 1 object file(s)
This time, we don’t see any output. As an alternative, PythoC creates a construct listing beneath your present listing, then creates an executable file there you could run.
(pythoc_test) C:Usersthomaprojectspythoc_test>dir buildtest4*
Quantity in drive C is Home windows
Quantity Serial Quantity is EEB4-E9CA
Listing of C:Usersthomaprojectspythoc_testbuild
26/02/2026 14:32 297 test4.deps
26/02/2026 14:32 168,448 test4.exe
26/02/2026 14:32 633 test4.ll
26/02/2026 14:32 412 test4.o
26/02/2026 14:32 0 test4.o.lock
26/02/2026 14:32 1,105,920 test4.pdb
We are able to run the test4.exe file simply as we’d some other executable.
(pythoc_test) C:Usersthomaprojectspythoc_test>buildtest4.exe
(pythoc_test) C:Usersthomaprojectspythoc_test>
However wait a second. In our Python code, we explicitly requested to print the addition end result, however we don’t see any output. What’s happening?
The reply is that the built-in Python print() operate depends on the Python interpreter working within the background to determine how one can show objects. As a result of PythoC strips all of that away to construct a tiny, blazing-fast native executable, the print assertion will get stripped out.
To print to the display in a local binary, you need to use the usual C library operate: printf.
The way to use printf in PythoC
In C (and subsequently in PythoC), printing variables requires format specifiers. You write a string with a placeholder (like %d for a decimal integer), after which go the variable you wish to insert into that placeholder.
Right here is the way you replace our code to import the C printf operate and use it appropriately:
from pythoc import compile, i32, ptr, i8, extern
# 1. Inform PythoC to hyperlink to the usual C printf operate
@extern
def printf(fmt: ptr[i8], *args) -> i32:
go
@compile
def add(x: i32, y: i32) -> i32:
printf("Including 10 and 20 = %dn", x+y)
return x + y
@compile
def primary() -> i32:
end result = add(10, 20)
# 2. Use printf with a C-style format string.
# %d is the placeholder for our integer (end result).
# n provides a brand new line on the finish.
return 0
if __name__ == "__main__":
from pythoc import compile_to_executable
compile_to_executable()
Now, if we re-run the above code and run the ensuing executable, our output turns into what we anticipated.
(pythoc_test) C:Usersthomaprojectspythoc_test>python test5.py
Efficiently compiled to executable: buildtest5.exe
Linked 1 object file(s)
(pythoc_test) C:Usersthomaprojectspythoc_test>buildtest5.exe
Including 10 and 20 = 30
Is it actually definitely worth the trouble, although?
All of the issues we’ve talked about will solely be price it if we see actual pace enhancements in our code. So, for our remaining instance, let’s see how briskly our compiled packages will be in comparison with the equal in Python, and that ought to reply our query definitively.
First, the common Python code. We’ll use a recursive Fibonacci calculation to simulate a long-running course of. Let’s calculate the fortieth Fibonacci quantity.
import time
def fib(n):
# This calculates the sequence recursively
if n <= 1:
return n
return fib(n - 1) + fib(n - 2)
if __name__ == "__main__":
print("Beginning Normal Python pace take a look at...")
start_time = time.time()
# fib(38) normally takes round 10 seconds in Python,
# relying in your pc's CPU.
end result = fib(40)
end_time = time.time()
print(f"Outcome: {end result}")
print(f"Time taken: {end_time - start_time:.4f} seconds")
I acquired this end result when working the above code.
(pythoc_test) C:Usersthomaprojectspythoc_test>python test6.py
Beginning Normal Python pace take a look at...
Outcome: 102334155
Time taken: 15.1611 seconds
Now for the PythoC-based code. Once more, as with the print assertion in our earlier instance, we will’t simply use the common import timing directive from Python for our timings. As an alternative, we’ve got to borrow the usual timing operate instantly from the C programming language: clock(). We outline this in the identical method because the printf assertion we used earlier.
Right here is the up to date PythoC script with the C timer in-built.
from pythoc import compile, i32, ptr, i8, extern
# 1. Import C's printf
@extern
def printf(fmt: ptr[i8], *args) -> i32:
go
# 2. Import C's clock operate
@extern
def clock() -> i32:
go
@compile
def fib(n: i32) -> i32:
if n <= 1:
return n
return fib(n - 1) + fib(n - 2)
@compile
def primary() -> i32:
printf("Beginning PythoC pace take a look at...n")
# Get the beginning time (this counts in "ticks")
start_time = clock()
# Run the heavy calculation
end result = fib(40)
# Get the tip time
end_time = clock()
# Calculate the distinction.
# Be aware: On Home windows, 1 clock tick = 1 millisecond.
elapsed_ms = end_time - start_time
printf("Outcome: %dn", end result)
printf("Time taken: %d millisecondsn", elapsed_ms)
return 0
if __name__ == "__main__":
from pythoc import compile_to_executable
compile_to_executable()
My output this time was,
(pythoc_test) C:Usersthomaprojectspythoc_test>python test7.py
Efficiently compiled to executable: buildtest7.exe
Linked 1 object file(s)
(pythoc_test) C:Usersthomaprojectspythoc_test>buildtest7.exe
Beginning PythoC pace take a look at...
Outcome: 102334155
Time taken: 308 milliseconds
And on this small instance, though the code is barely extra complicated, we see the actual benefit of utilizing compiled languages like C. Our executable was a whopping 40x sooner than the equal Python code. Not too shabby.
Who’s PythoC for?
I see three primary sorts of customers for PythoC.
1/ As we noticed in our Fibonacci pace take a look at, commonplace Python will be gradual when doing heavy mathematical lifting. PythoC could possibly be helpful for any Python developer constructing physics simulations, complicated algorithms, or customized data-processing pipelines who has hit a efficiency wall.
2/ Programmers who work intently with pc {hardware} (like constructing recreation engines, writing drivers, or programming small IoT gadgets) normally write in C as a result of they should handle pc reminiscence manually.
PythoC might attraction to those builders as a result of it presents the identical handbook reminiscence management (utilizing pointers and native sorts), nevertheless it lets them use Python as a “metaprogramming” engine to put in writing cleaner, extra versatile code earlier than it will get compiled all the way down to the {hardware} degree.
3/ In the event you write a useful Python script and wish to share it with a coworker, that coworker normally wants to put in Python, arrange a digital surroundings, and obtain your dependencies. It may be a trouble, notably if the goal person shouldn’t be very IT-literate. With PythoC, although, upon getting your compiled C executable, anybody can run it simply by double-clicking on the file.
And who it’s not for
The flip facet of the above is that PythoC might be not the very best software for an online developer, as efficiency bottlenecks there are normally community or database speeds, not CPU calculation speeds.
Likewise, if you’re already a person of optimised libraries comparable to NumPy, you received’t see many advantages both.
Abstract
This text launched to you the comparatively new and unknown PythoC library. With it, you need to use Python to create super-fast stand-alone C executable code.
I gave a number of examples of utilizing Python and the PythoC library to supply C executable packages, together with one which confirmed an unimaginable speedup when working the executable produced by the PythoC library in comparison with a regular Python program.
One subject you’ll run into is that Python imports aren’t supported in PythoC packages, however I additionally confirmed how one can work round this by changing them with equal C built-ins.
Lastly, I mentioned who I believed had been the sorts of Python programmers who may see a profit in utilizing PythonC of their workloads, and people who wouldn’t.
I hope this has whetted your urge for food for seeing what sorts of use circumstances you possibly can leverage PythoC for. You’ll be able to be taught far more about this convenient library by trying out the GitHub repo on the following hyperlink.
