script programa mundo interprete hola ejecutar desde consola compilar archivo python c linker compilation

programa - ¿Es factible compilar Python para código de máquina?



hola mundo python (12)

Algunas referencias adicionales:

¿Qué tan factible sería compilar Python (posiblemente a través de una representación C intermedia) en código de máquina?

Presumiblemente, necesitaría vincularse a una biblioteca en tiempo de ejecución de Python, y cualquier parte de la biblioteca estándar de Python que fuera Python necesitaría ser compilada (y vinculada también).

Además, necesitaría agrupar el intérprete de Python si deseaba hacer una evaluación dinámica de las expresiones, pero tal vez un subconjunto de Python que no permitiera esto aún sería útil.

¿Proporcionaría alguna velocidad y / o ventajas de uso de memoria? Presumiblemente, el tiempo de inicio del intérprete de Python se eliminaría (aunque las bibliotecas compartidas aún necesitarían cargarse al inicio).


Como dice @Greg Hewgill, hay buenas razones por las que esto no siempre es posible. Sin embargo, ciertos tipos de código (como el código muy algorítmico) se pueden convertir en códigos de máquina "reales".

Hay varias opciones:

  • Use Psyco , que emite código de máquina de forma dinámica. Sin embargo, debes elegir cuidadosamente qué métodos / funciones convertir.
  • Use Cython , que es un lenguaje similar a Python que se compila en una extensión de Python C
  • Utilice PyPy , que tiene un traductor de RPython (un subconjunto restringido de Python que no admite algunas de las características más "dinámicas" de Python) para C o LLVM.
    • PyPy sigue siendo altamente experimental
    • no todas las extensiones estarán presentes

Después de eso, puede usar uno de los paquetes existentes (congelar, Py2exe, PyInstaller) para poner todo en un solo archivo binario.

En general: no hay una respuesta general para su pregunta. Si tiene un código de Python que es crítico para el rendimiento, intente utilizar tanta funcionalidad incorporada como sea posible (o pregunte "¿Cómo hago para que mi código Python sea más rápido?"). Si eso no ayuda, intente identificar el código y transferirlo a C (o Cython) y usar la extensión.


Esto no compila Python al código de máquina. Pero permite crear una biblioteca compartida para llamar al código de Python.

Si lo que estás buscando es una manera fácil de ejecutar código Python desde C sin depender de cosas de execp. Puede generar una biblioteca compartida desde el código python incluido con unas pocas llamadas a la API de incrustación de Python . Bueno, la aplicación es una biblioteca compartida, una .so que puede usar en muchas otras bibliotecas / aplicaciones.

Aquí hay un ejemplo simple que crea una biblioteca compartida, que puede vincular con un programa C. La biblioteca compartida ejecuta el código de Python.

El archivo python que se ejecutará es pythoncalledfromc.py :

# -*- encoding:utf-8 -*- # this file must be named "pythoncalledfrom.py" def main(string): # args must a string print "python is called from c" print "string sent by «c» code is:" print string print "end of «c» code input" return 0xc0c4 # return something

Puede intentarlo con python2 -c "import pythoncalledfromc; pythoncalledfromc.main(''HELLO'') . Se generará:

python is called from c string sent by «c» code is: HELLO end of «c» code input

La biblioteca compartida estará definida por lo siguiente por callpython.h :

#ifndef CALL_PYTHON #define CALL_PYTHON void callpython_init(void); int callpython(char ** arguments); void callpython_finalize(void); #endif

El callpython.c asociado es:

// gcc `python2.7-config --ldflags` `python2.7-config --cflags` callpython.c -lpython2.7 -shared -fPIC -o callpython.so #include <stdlib.h> #include <stdio.h> #include <string.h> #include <python2.7/Python.h> #include "callpython.h" #define PYTHON_EXEC_STRING_LENGTH 52 #define PYTHON_EXEC_STRING "import pythoncalledfromc; pythoncalledfromc.main(/"%s/")" void callpython_init(void) { Py_Initialize(); } int callpython(char ** arguments) { int arguments_string_size = (int) strlen(*arguments); char * python_script_to_execute = malloc(arguments_string_size + PYTHON_EXEC_STRING_LENGTH); PyObject *__main__, *locals; PyObject * result = NULL; if (python_script_to_execute == NULL) return -1; __main__ = PyImport_AddModule("__main__"); if (__main__ == NULL) return -1; locals = PyModule_GetDict(__main__); sprintf(python_script_to_execute, PYTHON_EXEC_STRING, *arguments); result = PyRun_String(python_script_to_execute, Py_file_input, locals, locals); if(result == NULL) return -1; return 0; } void callpython_finalize(void) { Py_Finalize(); }

Puedes compilarlo con el siguiente comando:

gcc `python2.7-config --ldflags` `python2.7-config --cflags` callpython.c -lpython2.7 -shared -fPIC -o callpython.so

Cree un archivo llamado callpythonfromc.c que contenga lo siguiente:

#include "callpython.h" int main(void) { char * example = "HELLO"; callpython_init(); callpython(&example); callpython_finalize(); return 0; }

Compilarlo y ejecutar:

gcc callpythonfromc.c callpython.so -o callpythonfromc PYTHONPATH=`pwd` LD_LIBRARY_PATH=`pwd` ./callpythonfromc

Este es un ejemplo muy básico. Puede funcionar, pero dependiendo de la biblioteca puede ser difícil serializar estructuras de datos C a Python y de Python a C. Las cosas se pueden automatizar de alguna manera ...

Nuitka podría ser útil.

También hay numba pero ambos no pretenden hacer exactamente lo que quieres. Es posible generar un encabezado C a partir del código Python, pero solo si especifica cómo convertir los tipos Python a tipos C o puede inferir esa información. Ver python astroid para un analizador Python ast.


Esto puede parecer razonable a primera vista, sin embargo, hay muchas cosas ordinarias en Python que no se pueden asignar directamente a una representación en C sin tener que soportar gran parte del soporte de tiempo de ejecución de Python. Por ejemplo, me viene a la mente el tipado de patos. Muchas funciones en Python que leen entrada pueden tomar un archivo o un objeto similar a un archivo, siempre y cuando admita ciertas operaciones, por ej. read () o readline (). Si piensa en qué se necesitaría para asignar este tipo de soporte a C, comenzará a imaginar exactamente el tipo de cosas que el sistema de tiempo de ejecución de Python ya hace.

Hay utilidades como py2exe que py2exe un programa de Python y el tiempo de ejecución en un único ejecutable (en la medida de lo posible).


Jython tiene un compilador que apunta al bytecode de JVM. ¡El bytecode es completamente dinámico, al igual que el lenguaje Python mismo! Muy genial. (Sí, como alude la respuesta de Greg Hewgill, el bytecode usa el tiempo de ejecución de Jython, por lo que el archivo Jython debe distribuirse con su aplicación).


La respuesta es "Sí, es posible". Puede tomar el código Python e intentar compilarlo en el código C equivalente utilizando la API CPython. De hecho, solía haber un proyecto de Python2C que hacía justamente eso, pero no he oído hablar de él en muchos años (en el Python 1.5 días es la última vez que lo vi).

Podría intentar traducir el código de Python al C nativo tanto como sea posible, y recurrir a la API de CPython cuando necesite las características de Python reales. He estado jugando con esa idea el último mes o dos. Sin embargo, es un montón de trabajo, y una gran cantidad de características de Python son muy difíciles de traducir en C: funciones anidadas, generadores, cualquier cosa menos simples clases con métodos simples, cualquier cosa que implique la modificación de módulos globales desde fuera del módulo, etc. , etc.


Pruebe el ShedSkin Python-to-C ++, pero está lejos de ser perfecto. También está Psyco - Python JIT si solo se necesita aceleración. Pero en mi humilde opinión esto no vale la pena el esfuerzo. Para las partes críticas de la velocidad del código, la mejor solución sería escribirlas como extensiones C / C ++.



Psyco es una especie de compilador just-in-time (JIT): compilador dinámico para Python, ejecuta código 2-100 veces más rápido, pero necesita mucha memoria.

En resumen: ejecuta su software Python existente mucho más rápido, sin cambios en su fuente, pero no se compila al código objeto de la misma forma que un compilador de C.


Pyrex es un subconjunto del lenguaje Python que compila para C, hecho por el tipo que primero compiló listas de comprensión para Python. Se desarrolló principalmente para envoltorios de construcción, pero se puede utilizar en un contexto más general. Cython es una horquilla de pyrex mantenida más activamente.


Nuitka es un compilador de Python a C ++ que enlaza con libpython. Parece ser un proyecto relativamente nuevo. El autor reclama una mejora de velocidad sobre CPython en el benchmark pystone.


PyPy es un proyecto para volver a implementar Python en Python, utilizando la compilación para el código nativo como una de las estrategias de implementación (otros son una VM con JIT, usando JVM, etc.). Sus versiones C compiladas son más lentas que CPython en promedio, pero mucho más rápidas para algunos programas.

Shedskin es un compilador experimental de Python a C ++.

Pyrex es un lenguaje especialmente diseñado para escribir módulos de extensión de Python. Está diseñado para cerrar la brecha entre el mundo agradable, de alto nivel y fácil de usar de Python y el desordenado mundo de bajo nivel de C.