El otro día encontré una biblioteca interesante de la que nunca había oído hablar antes.

PythonC es un compilador de lenguaje de dominio específico (DSL) que permite a los desarrolladores escribir programas en C utilizando la sintaxis estándar de Python. Toma un subconjunto de código Python escrito estáticamente y lo compila directamente en código de máquina nativo a través de LLVM IR (representación intermedia de máquina virtual de bajo nivel).

LLVM IR es un Formato de código independiente de la plataforma utilizado internamente por el marco del compilador LLVM. Los compiladores primero traducen el código fuente a LLVM IR y luego LLVM transforma ese IR en código de máquina optimizado para CPU específicas (x86, ARM, etc.).

Una filosofía de diseño central de PythoC es: Tiempo de ejecución equivalente al tiempo de compilación basado en C + Python, y tiene los siguientes puntos de venta casi exclusivos.

1. Crea ejecutables nativos independientes.

A diferencia de herramientas como Cython, que se utilizan principalmente para crear extensiones C para acelerar los scripts Python existentes, PythoC puede generar ejecutables estilo C completamente independientes e independientes. Una vez compilado, el binario resultante no requiere la ejecución del intérprete de Python ni de un recolector de basura.

2. Tiene control de bajo nivel con sintaxis de Python.

PythoC refleja las características de C, pero las envuelve en la sintaxis más limpia de Python. Para lograr esto, utiliza sugerencias de tipos nativos de la máquina en lugar de los tipos dinámicos estándar de Python.

  • Primitivos: i32, i8, f64, etc.
  • Estructuras de la memoria: Punteros (ptr[T]), matrices (matriz[T, N]) y estructuras (creadas decorando clases estándar de Python).
  • Gestión manual de la memoria: Al no utilizar un recolector de basura de forma predeterminada, la gestión de la memoria es explícita, como en C. Sin embargo, ofrece controles de seguridad modernos y opcionales, como tipos lineales (que garantizan que cada asignación se desasigne explícitamente para evitar fugas) y tipos de refinamiento (para hacer cumplir las comprobaciones de validación en tiempo de compilación).

Python como motor de metaprogramación

Una de las características más poderosas de PythoC es la gestión de pasos de compilación. Debido a que el entorno de tiempo de compilación es solo Python, puede usar la lógica estándar de Python para generar, manipular y especializar su código PythoC. antes está compilado para LLVM. Esto ofrece capacidades de generación de código en tiempo de compilación muy flexibles (similares a las plantillas de C++, pero impulsadas por Python puro).

Suena prometedor, pero ¿la realidad está a la altura de las expectativas? Bien, veamos esta biblioteca en acción. La instalación es fácil, como la mayoría de las bibliotecas de Python, es solo una instalación de pip como esta:

pip install pythoc

Pero probablemente sea mejor configurar un entorno de desarrollo adecuado donde puedas aislar tus diferentes proyectos. En mi ejemplo, estoy usando la utilidad UV, pero use el método con el que se sienta más cómodo. Ingrese los siguientes comandos en su terminal de línea de comandos.

C:Usersthomaprojects> cd projects
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 install pythoc

Un ejemplo sencillo

Para usar PythoC, debe definir funciones usando tipos de máquinas específicos y etiquetarlas con la compilación de PythoC. decorador. Hay dos formas principales de ejecutar su código PythoC. Puedes llamar a la biblioteca compilada directamente desde Python de esta manera,

from pythoc import compile, i32

@compile
def add(x: i32, y: i32) -> i32:
    return x + y

# Can compile to native code
@compile
def main() -> i32:
    return add(10, 20)

# Call the compiled dynamic library from Python directly
result = main()
print(result)

Así que ejecútelo así.

(pythoc_test) C:Usersthomaprojectspythoc_test>python test1.py

30

O puede crear un ejecutable independiente que pueda ejecutarse independientemente de Python. Para hacer esto, use un código como este.

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 main() -> i32:
    return add(10, 20)

if __name__ == "__main__":
    from pythoc import compile_to_executable
    compile_to_executable()

Lo ejecutamos de la misma manera.

(pythoc_test) C:Usersthomaprojectspythoc_test>python test4.py

Successfully compiled to executable: buildtest4.exe
Linked 1 object file(s)

Esta vez no vemos salida. En cambio, PythoC crea un directorio de compilación debajo del directorio actual y luego crea un archivo ejecutable que puede ejecutar.

(pythoc_test) C:Usersthomaprojectspythoc_test>dir buildtest4*
 Volume in drive C is Windows
 Volume Serial Number is EEB4-E9CA

 Directory 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

Podemos ejecutar el archivo test4.exe tal como lo haríamos con cualquier otro ejecutable.

(pythoc_test) C:Usersthomaprojectspythoc_test>buildtest4.exe

(pythoc_test) C:Usersthomaprojectspythoc_test>

Pero espera un segundo. En nuestro código Python, solicitamos explícitamente imprimir el resultado de la suma, pero no vemos ningún resultado. ¿Lo que está sucediendo?

La respuesta es que la función print() incorporada de Python se basa en el intérprete de Python que se ejecuta en segundo plano para descubrir cómo mostrar los objetos. Debido a que PythoC elimina todo esto para crear un ejecutable nativo pequeño y ultrarrápido, se elimina la declaración de impresión.

Para imprimir en la pantalla en un binario nativo, debe usar la función de biblioteca C estándar: printf.

Cómo usar printf en PythoC

En C (y por lo tanto en PythoC), la impresión de variables requiere especificadores de formato. Escribe una cadena con un marcador de posición (como %d para un entero decimal) y luego pasa la variable que desea insertar en ese marcador de posición.

Así es como actualiza nuestro código para importar la función C printf y usarla correctamente:

from pythoc import compile, i32, ptr, i8, extern

# 1. Tell PythoC to link to the standard C printf function
@extern
def printf(fmt: ptr[i8], *args) -> i32:
    pass

@compile
def add(x: i32, y: i32) -> i32:
  
    printf("Adding 10 and 20 = %dn", x+y)
    return x + y

@compile
def main() -> i32:
    result = add(10, 20)
    
    # 2. Use printf with a C-style format string. 
    # %d is the placeholder for our integer (result).
    # n adds a new line at the end.
   
    
    return 0

if __name__ == "__main__":
    from pythoc import compile_to_executable
    compile_to_executable()

Ahora, si volvemos a ejecutar el código anterior y ejecutamos el ejecutable resultante, nuestro resultado será el que esperábamos.

(pythoc_test) C:Usersthomaprojectspythoc_test>python test5.py
Successfully compiled to executable: buildtest5.exe
Linked 1 object file(s)

(pythoc_test) C:Usersthomaprojectspythoc_test>buildtest5.exe
Adding 10 and 20 = 30

¿Pero realmente vale la pena preocuparse?

Todo lo que hablamos sólo valdrá la pena si vemos mejoras reales en la velocidad de nuestro código. Entonces, para nuestro ejemplo final, veamos qué tan rápido se pueden comparar nuestros programas compilados con sus equivalentes de Python, y eso debería responder nuestra pregunta definitivamente.

Primero, código Python normal. Usaremos un cálculo recursivo de Fibonacci para simular un proceso de larga duración. Calculemos el cuadragésimo número de Fibonacci.

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("Starting Standard Python speed test...")
    
    start_time = time.time()
    
    # fib(38) usually takes around 10 seconds in Python, 
    # depending on your computer's CPU.
    result = fib(40) 
    
    end_time = time.time()
    
    print(f"Result: {result}")
    print(f"Time taken: {end_time - start_time:.4f} seconds")

Obtuve este resultado al ejecutar el código anterior.

(pythoc_test) C:Usersthomaprojectspythoc_test>python test6.py
Starting Standard Python speed test...
Result: 102334155
Time taken: 15.1611 seconds

Ahora veamos el código basado en PythoC. Nuevamente, al igual que con la declaración de impresión en nuestro ejemplo anterior, no podemos simplemente usar la directiva de tiempo de importación habitual de Python para nuestros tiempos. En lugar de ello, tenemos que tomar prestada la función de temporización estándar directamente del lenguaje de programación C: reloj(). Definimos esto de la misma manera que la declaración printf que usamos anteriormente.

Aquí está el script PythoC actualizado con el temporizador C incorporado.

from pythoc import compile, i32, ptr, i8, extern

# 1. Import C's printf
@extern
def printf(fmt: ptr[i8], *args) -> i32:
    pass

# 2. Import C's clock function
@extern
def clock() -> i32:
    pass

@compile
def fib(n: i32) -> i32:
    if n <= 1:
        return n
    return fib(n - 1) + fib(n - 2)

@compile
def main() -> i32:
    printf("Starting PythoC speed test...n")
    
    # Get the start time (this counts in "ticks")
    start_time = clock()
    
    # Run the heavy calculation
    result = fib(40)
    
    # Get the end time
    end_time = clock()
    
    # Calculate the difference. 
    # Note: On Windows, 1 clock tick = 1 millisecond.
    elapsed_ms = end_time - start_time
    
    printf("Result: %dn", result)
    printf("Time taken: %d millisecondsn", elapsed_ms)
    
    return 0

if __name__ == "__main__":
    from pythoc import compile_to_executable
    compile_to_executable()

Mi salida esta vez fue,

(pythoc_test) C:Usersthomaprojectspythoc_test>python test7.py
Successfully compiled to executable: buildtest7.exe
Linked 1 object file(s)

(pythoc_test) C:Usersthomaprojectspythoc_test>buildtest7.exe
Starting PythoC speed test...
Result: 102334155
Time taken: 308 milliseconds

Y en este pequeño ejemplo, aunque el código es un poco más complejo, vemos la ventaja real de usar lenguajes compilados como C. Nuestro ejecutable era 40 veces más rápido que el código Python equivalente. Nada mal.

¿Para quién es PythoC?

Veo tres tipos principales de usuarios de PythoC.

1/ Como vimos en nuestra prueba de velocidad de Fibonacci, Python estándar puede ser lento cuando se realizan trabajos matemáticos pesados. PythoC puede ser útil para cualquier desarrollador de Python que cree simulaciones físicas, algoritmos complejos o canales de procesamiento de datos personalizados que hayan alcanzado un límite de rendimiento.

2/ Los programadores que trabajan estrechamente con el hardware de la computadora (como construir motores de juegos, escribir controladores o programar pequeños dispositivos IoT) a menudo escriben en C porque necesitan administrar manualmente la memoria de la computadora.

PythoC podría atraer a estos desarrolladores porque ofrece el mismo control manual de la memoria (usando punteros y tipos nativos), pero les permite usar Python como un motor de “metaprogramación” para escribir código más limpio y flexible antes de compilarlo al nivel de hardware.

3/ Si escribe un script de Python útil y desea compartirlo con un compañero de trabajo, ese compañero de trabajo normalmente necesitará instalar Python, configurar un entorno virtual y descargar sus dependencias. Puede ser una molestia, especialmente si el usuario objetivo no tiene muchos conocimientos de TI. Sin embargo, con PythoC, después de compilar el ejecutable en C, cualquiera puede ejecutarlo simplemente haciendo doble clic en el archivo.

Y para los que no lo son

La otra cara de lo anterior es que PythoC probablemente no sea la mejor herramienta para un desarrollador web, ya que los cuellos de botella en el rendimiento generalmente ocurren en las velocidades de la red o de la base de datos en lugar de en las velocidades de cálculo de la CPU.

Del mismo modo, si ya eres usuario de bibliotecas optimizadas como NumPy, tampoco verás muchos beneficios.

Resumen

Este artículo le presentó la biblioteca PythoC relativamente nueva y desconocida. Con él, puedes usar Python para crear código ejecutable C independiente súper rápido.

He dado varios ejemplos del uso de Python y la biblioteca PythoC para producir programas ejecutables en C, incluido uno que mostró una velocidad increíble al ejecutar el ejecutable producido por la biblioteca PythoC en comparación con un programa Python estándar.

Un problema que encontrará es que las importaciones de Python no son compatibles con los programas PythoC, pero también he mostrado cómo solucionarlo reemplazándolos con componentes C equivalentes.

Finalmente, hablé sobre quiénes pensaba que eran los tipos de programadores de Python que podrían ver beneficios al usar PythonC en sus cargas de trabajo y aquellos que no.

Espero que esto haya despertado su apetito por ver para qué tipos de casos de uso puede aprovechar PythoC. Puede obtener mucho más información sobre esta útil biblioteca consultando el repositorio de GitHub en el siguiente enlace.

https://github.com/1flei/PythoC

Fuente