Compile el programa principal de Python usando Cython

81

Tengo un programa Python2.6 que puede cargar módulos de Python compilados en archivos .so usando Cython. Usé Cython para compilar los módulos .py en archivos .so y todo funciona bien.

Este es el archivo setup.py que uso con Cython:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [
    Extension("ldap", ["ldap.pyx"]),
    Extension("checker", ["checker.pyx"]),
    Extension("finder", ["finder.pyx"]),
    Extension("utils", ["utils.pyx"]),
]

setup(
  name = 'bchecker',
  cmdclass = {'build_ext': build_ext},
  ext_modules = ext_modules
)

Entonces sé que puedo compilar módulos Python usando Cython (supongo que Cython crea archivos 'C' a partir de mis archivos Python y luego los compila), pero ¿puedo compilar mi programa Python principal en algo que pueda ejecutar en una plataforma Linux? Si es así, se agradecería un ejemplo de línea de comandos de Cython. Gracias.

mozza
fuente
4
¿Alguna de estas respuestas fue útil? ¿Conseguiste que esto funcione? Si es así, acepte una respuesta
Mike Pennington
3
Dudo que esto se marque alguna vez: el usuario fue visto por última vez un día después de la fecha de edición de la pregunta.
Broken Man

Respuestas:

152

Al contrario de lo que afirman Adam Matan y otros, de hecho puede crear un solo archivo binario ejecutable usando Cython, a partir de un archivo Python (.py) puro.

Sí, Cython está diseñado para usarse como se indica, como una forma de simplificar la escritura de módulos de extensión C / C ++ para el tiempo de ejecución de CPython python.

Pero, como nudzo alude en este comentario , puede usar el --embedinterruptor en la línea de comandos.

He aquí un ejemplo extremadamente sencillo. Estoy realizando esto desde una estación de trabajo Debian Sid, usando python3 y cython3 ..

Asegúrese de tener los paquetes python-dev o python3-dev instalados de antemano.

1) Cree un programa Python muy simple llamado hello.py

$ gato hello.py

print ("¡Hola mundo!")

2) Utilice Cython para compilar su programa Python en C ...

cython3 --embed -o hello.c hello.py

3) Utilice GCC para compilar hello.c en un archivo ejecutable llamado hello ...

gcc -Os -I /usr/include/python3.3m -o hello hello.c -lpython3.3m -lpthread -lm -lutil -ldl

4) Terminas con un archivo llamado hola ...

$ file hola

hola: ejecutable LSB ELF de 64 bits, x86-64, versión 1 (SYSV), vinculado dinámicamente (usa bibliotecas compartidas), para GNU / Linux 2.6.32, BuildID [sha1] = 006f45195a26f1949c6ed051df9cbd4433e1ac23, no eliminado

$ ldd hello
linux-vdso.so.1 (0x00007fff273fe000)
libpython3.3m.so.1.0 => /usr/lib/x86_64-linux-gnu/libpython3.3m.so.1.0 (0x00007fc61dc2c000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc61da0f000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc61d70b000)
libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007fc61d508000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc61d304000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc61cf5a000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fc61cd52000)
libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007fc61cb28000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fc61c90f000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc61e280000)

En este caso, el ejecutable está vinculado dinámicamente a Python 3.3 en mi sistema Debian.

5) corre hola ...

$ ./hello

Hola Mundo!

Como puede ver, con este método, básicamente puede usar Cython para convertir sus aplicaciones Python puras en código objeto compilado y ejecutable.

Estoy usando este método para aplicaciones mucho más complejas, por ejemplo, una aplicación Python / PySide / Qt completa.

Para diferentes versiones de Python, usted adapta el gcc -Iy los -lconmutadores para que se adapten.

Luego puede empaquetar el ejecutable como un archivo de distribución (.deb, etc.), sin tener que empaquetar los archivos Python / PySide / Qt; la ventaja es que su aplicación aún debería poder ejecutarse incluso después de una actualización de distribución al mismo versiones de Python, etc. en esa distribución.

Hombre roto
fuente
¿Se puede utilizar este método de incrustación para generar una biblioteca dinámica en lugar de ejecutable?
denfromufa
5
No compila módulo (s) en el ejecutable. ¿Es posible tener un ejecutable portátil, es decir, cada módulo que se haya importado en el código fuente se compilará en ese ejecutable? @BrokenMan
Devesh Saini
1
@DeveshSaini No he pasado el tiempo tratando de resolver esa parte. La única forma en que me las arreglé para obtener una aplicación python + Pyside completa para compilar como se indicó anteriormente, fue desarrollar el programa de la manera normal: muchas declaraciones incluyen <mymodule> + pruebas con el intérprete. Luego, cuando todo está listo, pego manualmente todo el código incluido y comento las declaraciones de inclusión relevantes que reemplazaron. Sí, no es deseable, pero como dije al principio, no he perdido el tiempo para ver cómo puedo compilar solo la rutina principal y vincular los módulos incluidos.
Broken Man
3
¿Qué pasa con el enlace estático de libpython?
James Mills
4
Para python 2.7 cython --embed -o /tmp/a.c a.pyygcc -Os -I /usr/include/python2.7 -o /tmp/a/tmp/a.c -lpython2.7 -lpthread -lm -lutil -ldl
dsaydon
17

Eche un vistazo a las respuestas a ¿Puede Cython compilar en un EXE? que, contrariamente a todas las otras respuestas aquí, dice que sí, es posible compilar en un ejecutable.

Los enlaces en Embedding Cython parecen ser un buen lugar para comenzar, pero no es el propósito principal de Cython, por lo que no sé qué tan sencillo sería.

Scott Griffiths
fuente
1
Gracias por los enlaces. También sospecho que puede ser posible, ya que uso Python para crear archivos .so que contienen código ejecutable.
mozza
4

No sé si esto ayudará o no, pero Nudzo tiene razón. Puede obtenerlo cython --embed -o main.o main.pyy luego trato de compilar el resultado con cl / EHsc

Jake Cook
fuente
-21

No puede, Cython no está hecho para compilar Python ni convertirlo en un ejecutable.

Para producir un archivo .exe, use py2exe .

Para producir un paquete para Mac o Linux, use el proceso del sistema de empaquetado regulard ya que no hay nada específico sobre un programa de lenguaje de script en Unix env.

e-satis
fuente
2
Bueno, me permite convertir mis archivos .py en archivos .so. Vea el script anterior que uso. ¿No contienen los archivos .so código ejecutable?
mozza
No es el propósito. Cython es para compilar extensiones Python C / C ++, no convertir scripts Python en ejecutables.
e-satis
9
Desinformación. Hay lo cython --embedque puede producir ejecutables con incrustar Python.
nudzo
El ejecutable resultante aún depende de libpython a menos que lo vincule estáticamente. Además, no producirá un ejecutable de todos sus archivos, sino un ejecutable de su punto de entrada.
e-satis
2
@ e-satis Sí, el ejecutable se vinculará dinámicamente a la versión de libpython con la que se compiló en ese momento. ¿Cual es el problema? Si es para Linux, y si está planeando distribuir su aplicación, simplemente empaquétela en cualquier formato de distribución de Linux al que se dirija, como cualquier otro paquete binario. por ejemplo, myapp_1_wheezy_amd64.deb sería su aplicación de python compilada vinculada con python2 o python3 para esa distribución. Para Windows, solo proporcione el python requerido. Una vez más, no veo el problema aquí, ni la objeción.
Broken Man