neulich eine interessante Bibliothek, von der ich vorher noch nie gehört hatte.
PythoC ist ein Area-Particular Language (DSL)-Compiler, der es Entwicklern ermöglicht, C-Programme mit der Customary-Python-Syntax zu schreiben. Es nimmt eine statisch typisierte Teilmenge des Python-Codes und kompiliert ihn über LLVM IR (Low Degree Digital Machine Intermediate Illustration) direkt in nativen Maschinencode.
LLVM IR ist ein plattformunabhängiges Codeformat, das intern vom LLVM-Compiler-Framework verwendet wird. Compiler übersetzen den Quellcode zunächst in LLVM-IR, und dann wandelt LLVM diese IR in optimierten Maschinencode für bestimmte CPUs (x86, ARM usw.) um.
Eine zentrale Designphilosophie von PythoC ist: C-äquivalente Laufzeit + Python-basierte Kompilierungszeit, und es hat die folgenden nahezu Alleinstellungsmerkmale.
1. Erstellt eigenständige native ausführbare Dateien
Im Gegensatz zu Instruments wie Cython, die hauptsächlich zum Erstellen von C-Erweiterungen zur Beschleunigung bestehender Python-Skripte verwendet werden, kann PythoC völlig unabhängige, eigenständige ausführbare Dateien im C-Stil generieren. Nach der Kompilierung benötigt die resultierende Binärdatei weder den Python-Interpreter noch einen Rubbish Collector, um ausgeführt zu werden.
2. Verfügt über Low-Degree-Steuerung mit Python-Syntax
PythoC spiegelt die Fähigkeiten von C wider, verpackt sie jedoch in die sauberere Syntax von Python. Um dies zu erreichen, werden maschinennative Typhinweise anstelle der standardmäßigen dynamischen Typen von Python verwendet.
- Primitive: i32, i8, f64 usw.
- Gedächtnisstrukturen: Zeiger (ptr(T)), Arrays (array(T, N)) und Strukturen (erstellt durch Dekoration von Customary-Python-Klassen).
- Manuelle Speicherverwaltung: Da es standardmäßig keinen Rubbish Collector verwendet, ist die Speicherverwaltung genau wie in C explizit. Es bietet jedoch moderne, optionale Sicherheitsprüfungen, wie z lineare Typen (die sicherstellen, dass jede Zuweisung explizit freigegeben wird, um Lecks zu verhindern) und Verfeinerungsarten (um Validierungsprüfungen zur Kompilierungszeit zu erzwingen).
Python als Metaprogrammierungs-Engine
Eine der leistungsstärksten Funktionen von PythoC ist die Handhabung des Kompilierungsschritts. Da es sich bei der Kompilierungszeitumgebung nur um Python handelt, können Sie Customary-Python-Logik verwenden, um Ihren PythoC-Code zu generieren, zu bearbeiten und zu spezialisieren vor es wird auf LLVM herunterkompiliert. Dies bietet Ihnen hochflexible Funktionen zur Codegenerierung zur Kompilierungszeit (ähnlich wie C++-Vorlagen, aber angetrieben durch reines Python).
Es klingt vielversprechend, aber wird die Realität dem Hype gerecht? Okay, sehen wir uns diese Bibliothek in Aktion an. Die Set up ist einfach, wie bei den meisten Python-Bibliotheken ist es nur eine Pip-Set up wie diese:
pip set up pythoc
Aber es ist wahrscheinlich besser, eine geeignete Entwicklungsumgebung einzurichten, in der Sie Ihre verschiedenen Projekte isolieren können. In meinem Beispiel verwende ich das UV-Dienstprogramm, aber verwende die Methode, mit der du am besten zurechtkommst. Geben Sie die folgenden Befehle in Ihr Befehlszeilenterminal ein.
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
Ein einfaches Beispiel
Um PythoC zu verwenden, definieren Sie Funktionen mithilfe bestimmter Maschinentypen und markieren sie mit der Kompilierung von PythoC Dekorateur. Es gibt zwei Möglichkeiten, Ihren PythoC-Code auszuführen. Sie können die kompilierte Bibliothek wie folgt direkt aus Python aufrufen:
from pythoc import compile, i32
@compile
def add(x: i32, y: i32) -> i32:
return x + y
# Can compile to native code
@compile
def important() -> i32:
return add(10, 20)
# Name the compiled dynamic library from Python immediately
outcome = important()
print(outcome)
Führen Sie es dann so aus.
(pythoc_test) C:Usersthomaprojectspythoc_test>python test1.py
30
Oder Sie können eine eigenständige ausführbare Datei erstellen, die Sie unabhängig von Python ausführen können. Verwenden Sie dazu Code wie diesen.
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 important() -> i32:
return add(10, 20)
if __name__ == "__main__":
from pythoc import compile_to_executable
compile_to_executable()
Bei uns läuft es genauso.
(pythoc_test) C:Usersthomaprojectspythoc_test>python test4.py
Efficiently compiled to executable: buildtest4.exe
Linked 1 object file(s)
Dieses Mal sehen wir keine Ausgabe. Stattdessen erstellt PythoC ein Construct-Verzeichnis unterhalb Ihres aktuellen Verzeichnisses und erstellt dort dann eine ausführbare Datei, die Sie ausführen können.
(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
Wir können die Datei test4.exe genauso ausführen wie jede andere ausführbare Datei.
(pythoc_test) C:Usersthomaprojectspythoc_test>buildtest4.exe
(pythoc_test) C:Usersthomaprojectspythoc_test>
Aber warte mal. In unserem Python-Code haben wir ausdrücklich darum gebeten, das Additionsergebnis zu drucken, aber wir sehen keine Ausgabe. Was ist los?
Die Antwort ist, dass die integrierte Python-Funktion print() darauf angewiesen ist, dass der Python-Interpreter im Hintergrund läuft, um herauszufinden, wie Objekte angezeigt werden. Da PythoC all das entfernt, um eine winzige, blitzschnelle native ausführbare Datei zu erstellen, wird die print-Anweisung entfernt.
Um in einer nativen Binärdatei auf dem Bildschirm zu drucken, müssen Sie die Customary-C-Bibliotheksfunktion verwenden: printf.
So verwenden Sie printf in PythoC
In C (und damit in PythoC) erfordert das Drucken von Variablen Formatbezeichner. Sie schreiben eine Zeichenfolge mit einem Platzhalter (wie %d für eine dezimale Ganzzahl) und übergeben dann die Variable, die Sie in diesen Platzhalter einfügen möchten.
So aktualisieren Sie unseren Code, um die C-Printf-Funktion zu importieren und korrekt zu verwenden:
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:
cross
@compile
def add(x: i32, y: i32) -> i32:
printf("Including 10 and 20 = %dn", x+y)
return x + y
@compile
def important() -> i32:
outcome = add(10, 20)
# 2. Use printf with a C-style format string.
# %d is the placeholder for our integer (outcome).
# n provides a brand new line on the finish.
return 0
if __name__ == "__main__":
from pythoc import compile_to_executable
compile_to_executable()
Wenn wir nun den obigen Code erneut ausführen und die resultierende ausführbare Datei ausführen, entspricht unsere Ausgabe unseren Erwartungen.
(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
Aber ist es die Mühe wirklich wert?
All die Dinge, über die wir gesprochen haben, werden sich nur dann lohnen, wenn wir in unserem Code echte Geschwindigkeitsverbesserungen sehen. Schauen wir uns additionally für unser letztes Beispiel an, wie schnell unsere kompilierten Programme mit dem Äquivalent in Python verglichen werden können, und das sollte unsere Frage endgültig beantworten.
Zuerst der reguläre Python-Code. Wir verwenden eine rekursive Fibonacci-Berechnung, um einen lang laufenden Prozess zu simulieren. Berechnen wir die vierzigste Fibonacci-Zahl.
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 Customary Python pace take a look at...")
start_time = time.time()
# fib(38) often takes round 10 seconds in Python,
# relying in your laptop's CPU.
outcome = fib(40)
end_time = time.time()
print(f"Consequence: {outcome}")
print(f"Time taken: {end_time - start_time:.4f} seconds")
Ich habe dieses Ergebnis erhalten, als ich den obigen Code ausgeführt habe.
(pythoc_test) C:Usersthomaprojectspythoc_test>python test6.py
Beginning Customary Python pace take a look at...
Consequence: 102334155
Time taken: 15.1611 seconds
Nun zum PythoC-basierten Code. Auch hier können wir, wie bei der print-Anweisung in unserem früheren Beispiel, nicht einfach die reguläre Import-Timing-Direktive von Python für unsere Timings verwenden. Stattdessen müssen wir die Customary-Timing-Funktion direkt aus der Programmiersprache C ausleihen: Uhr(). Wir definieren dies auf die gleiche Weise wie die printf-Anweisung, die wir zuvor verwendet haben.
Hier ist das aktualisierte PythoC-Skript mit integriertem C-Timer.
from pythoc import compile, i32, ptr, i8, extern
# 1. Import C's printf
@extern
def printf(fmt: ptr(i8), *args) -> i32:
cross
# 2. Import C's clock operate
@extern
def clock() -> i32:
cross
@compile
def fib(n: i32) -> i32:
if n <= 1:
return n
return fib(n - 1) + fib(n - 2)
@compile
def important() -> 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
outcome = fib(40)
# Get the top time
end_time = clock()
# Calculate the distinction.
# Observe: On Home windows, 1 clock tick = 1 millisecond.
elapsed_ms = end_time - start_time
printf("Consequence: %dn", outcome)
printf("Time taken: %d millisecondsn", elapsed_ms)
return 0
if __name__ == "__main__":
from pythoc import compile_to_executable
compile_to_executable()
Meine Ausgabe conflict dieses Mal:
(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...
Consequence: 102334155
Time taken: 308 milliseconds
Und in diesem kleinen Beispiel sehen wir, obwohl der Code etwas komplexer ist, den wahren Vorteil der Verwendung kompilierter Sprachen wie C. Unsere ausführbare Datei conflict satte 40-mal schneller als der entsprechende Python-Code. Nicht zu schäbig.
Für wen ist PythoC geeignet?
Ich sehe drei Haupttypen von Benutzern für PythoC.
1/ Wie wir in unserem Fibonacci-Geschwindigkeitstest gesehen haben, kann Customary-Python bei schweren mathematischen Aufgaben langsam sein. PythoC könnte für jeden Python-Entwickler nützlich sein, der physikalische Simulationen, komplexe Algorithmen oder benutzerdefinierte Datenverarbeitungspipelines erstellt und an eine Leistungsgrenze stößt.
2/ Programmierer, die eng mit Computerhardware zusammenarbeiten (z. B. Spiele-Engines erstellen, Treiber schreiben oder kleine IoT-Geräte programmieren), schreiben normalerweise in C, weil sie den Computerspeicher manuell verwalten müssen.
PythoC könnte für diese Entwickler attraktiv sein, weil es die gleiche manuelle Speichersteuerung bietet (mithilfe von Zeigern und nativen Typen), es ihnen aber ermöglicht, Python als „Metaprogrammierungs“-Engine zu verwenden, um saubereren, flexibleren Code zu schreiben, bevor er bis zur Hardwareebene kompiliert wird.
3/ Wenn Sie ein hilfreiches Python-Skript schreiben und es mit einem Kollegen teilen möchten, muss dieser normalerweise Python installieren, eine virtuelle Umgebung einrichten und Ihre Abhängigkeiten herunterladen. Dies kann problematisch sein, insbesondere wenn der Zielbenutzer nicht über große IT-Kenntnisse verfügt. Mit PythoC kann jedoch jeder, sobald Sie Ihre kompilierte ausführbare C-Datei haben, sie ausführen, indem Sie einfach auf die Datei doppelklicken.
Und für wen es nicht ist
Die Kehrseite des oben Gesagten ist, dass PythoC wahrscheinlich nicht das beste Software für einen Webentwickler ist, da Leistungsengpässe dort normalerweise in der Netzwerk- oder Datenbankgeschwindigkeit liegen und nicht in der CPU-Berechnungsgeschwindigkeit.
Wenn Sie bereits optimierte Bibliotheken wie NumPy verwenden, werden Sie ebenfalls nicht viele Vorteile sehen.
Zusammenfassung
In diesem Artikel wurde Ihnen die relativ neue und unbekannte PythoC-Bibliothek vorgestellt. Damit können Sie mit Python superschnellen, eigenständigen ausführbaren C-Code erstellen.
Ich habe mehrere Beispiele für die Verwendung von Python und der PythoC-Bibliothek zum Erstellen ausführbarer C-Programme gegeben, darunter eines, das eine unglaubliche Beschleunigung beim Ausführen der von der PythoC-Bibliothek erstellten ausführbaren Datei im Vergleich zu einem Customary-Python-Programm zeigte.
Ein Drawback, auf das Sie stoßen werden, ist, dass Python-Importe in PythoC-Programmen nicht unterstützt werden. Ich habe jedoch auch gezeigt, wie Sie dieses Drawback umgehen können, indem Sie sie durch gleichwertige C-Integrationen ersetzen.
Abschließend habe ich besprochen, wer meiner Meinung nach die Artwork von Python-Programmierern ist, die einen Vorteil darin sehen könnten, PythonC in ihren Arbeitslasten zu verwenden, und welche, die das nicht tun würden.
Ich hoffe, das hat Ihren Appetit geweckt, zu sehen, für welche Anwendungsfälle Sie PythoC nutzen können. Sie können viel mehr über diese nützliche Bibliothek erfahren, indem Sie sich das GitHub-Repo unter dem folgenden Hyperlink ansehen.
