Kompilieren Sie das Python-Hauptprogramm mit Cython

81

Ich habe ein Python2.6-Programm, das Python-Module laden kann, die mit Cython in .so-Dateien kompiliert wurden. Ich habe Cython verwendet, um die .py-Module zu .so-Dateien zu kompilieren, und alles funktioniert einwandfrei.

Dies ist die Datei setup.py, die ich mit Cython verwende:

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
)

Ich weiß also, dass ich Python-Module mit Cython kompilieren kann (ich denke, Cython erstellt 'C'-Dateien aus meinen Python-Dateien und kompiliert sie dann), aber kann ich mein Haupt-Python-Programm zu etwas kompilieren, das ich auf einer Linux-Plattform ausführen kann? In diesem Fall wäre ein Cython-Befehlszeilenbeispiel wünschenswert. Vielen Dank.

Mozza
quelle
4
War eine dieser Antworten nützlich? Hast du das zum Laufen gebracht? Wenn ja, bitte akzeptieren Sie eine Antwort
Mike Pennington
3
Ich bezweifle, dass dies jemals markiert wird - der Benutzer wurde zuletzt einen Tag nach dem Bearbeitungsdatum der Frage gesehen.
Broken Man

Antworten:

152

Im Gegensatz zu dem, was Adam Matan und andere behaupten, Sie können in der Tat eine ausführbare Binärdatei mit Cython erstellen, von einer reinen Python (Py) Datei.

Ja, Cython soll wie angegeben verwendet werden, um das Schreiben von C / C ++ - Erweiterungsmodulen für die CPython-Python-Laufzeit zu vereinfachen.

Wie Nudzo in diesem Kommentar anspielt , können Sie den --embedSchalter an der Eingabeaufforderung verwenden.

Hier ist ein äußerst einfaches Beispiel. Ich verwende dies von einer Debian Sid-Workstation aus mit Python3 und Cython3.

Stellen Sie sicher, dass Sie zuvor die Pakete python-dev oder python3-dev installiert haben.

1) Erstellen Sie ein sehr einfaches Python-Programm namens hello.py

$ cat hello.py

drucken ("Hallo Welt!")

2) Verwenden Sie Cython, um Ihr Python-Programm in C ...

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

3) Verwenden Sie GCC, um hello.c in eine ausführbare Datei namens hello ... zu kompilieren.

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

4) Am Ende erhalten Sie eine Datei namens Hallo ...

$ file hallo

Hallo: ELF 64-Bit-LSB-ausführbare Datei, x86-64, Version 1 (SYSV), dynamisch verknüpft (verwendet gemeinsam genutzte Bibliotheken), für GNU / Linux 2.6.32, BuildID [sha1] = 006f45195a26f1949c6ed051df9cbd4433e1ac23, nicht entfernt

$ 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)

In diesem Fall ist die ausführbare Datei auf meinem Debian-System dynamisch mit Python 3.3 verknüpft.

5) lauf hallo ...

$ ./Hallo

Hallo Welt!

Wie Sie sehen, können Sie mit dieser Methode Cython grundsätzlich verwenden, um Ihre reinen Python-Anwendungen in ausführbaren, kompilierten Objektcode zu konvertieren.

Ich verwende diese Methode für wesentlich komplexere Anwendungen - zum Beispiel eine vollständige Python / PySide / Qt-Anwendung.

Für verschiedene Versionen von Python passen Sie das gcc an -Iund -lwechseln entsprechend.

Sie können die ausführbare Datei dann als Distributionsdatei (.deb usw.) verpacken, ohne die Python / PySide / Qt-Dateien packen zu müssen. Der Vorteil besteht darin, dass Ihre Anwendung auch nach einem Distributionsupdate noch ausgeführt werden kann Versionen von Python usw. auf dieser Distribution.

Gebrochener Mann
quelle
Kann diese Einbettungsmethode verwendet werden, um eine dynamische Bibliothek anstelle einer ausführbaren Datei zu generieren?
Denfromufa
5
Es werden keine Module in die ausführbare Datei kompiliert. Ist es möglich, eine tragbare ausführbare Datei zu haben, dh jedes Modul, das in den Quellcode importiert wurde, würde in diese ausführbare Datei kompiliert. @BrokenMan
Devesh Saini
1
@DeveshSaini Ich habe nicht die Zeit damit verbracht, das herauszufinden. Die einzige Möglichkeit, eine vollständige Python + Pyside-Anwendung zum Kompilieren wie oben zu erhalten, bestand darin, das Programm auf normale Weise zu entwickeln - viele enthalten <mymodule> -Anweisungen + Tests mit dem Interpreter. Wenn alles fertig ist, füge ich den gesamten enthaltenen Code manuell ein und kommentiere die relevanten include-Anweisungen aus, die sie ersetzt haben. Ja, es ist unerwünscht, aber wie ich zuerst sagte, habe ich nicht die Zeit darauf verwendet, zu sehen, wie ich nur die Hauptroutine kompilieren und die enthaltenen Module miteinander verknüpfen kann.
Broken Man
3
Was ist mit der statischen Verknüpfung von libpython?
James Mills
4
Für Python 2.7 cython --embed -o /tmp/a.c a.pyundgcc -Os -I /usr/include/python2.7 -o /tmp/a/tmp/a.c -lpython2.7 -lpthread -lm -lutil -ldl
Dsaydon
17

Werfen Sie einen Blick auf die Antworten auf Kann Cython zu einer EXE kompilieren? die im Gegensatz zu allen anderen Antworten hier sagen, dass es ja möglich ist, zu einer ausführbaren Datei zu kompilieren.

Die Links bei Embedding Cython scheinen ein guter Anfang zu sein, aber es ist nicht Cythons Hauptzweck, daher weiß ich nicht, wie einfach es sein würde.

Scott Griffiths
quelle
1
Danke für die Links. Ich vermute auch, dass dies möglich ist, da ich mit Python .so-Dateien erstelle, die ausführbaren Code enthalten.
Mozza
4

Ich weiß nicht, ob das helfen wird oder nicht, aber Nudzo ist richtig. Sie können es mit bekommen cython --embed -o main.o main.pyund dann versuche ich, das Ergebnis mit cl / EHsc zu kompilieren

Jake Cook
quelle
-21

Sie können nicht, Cython ist nicht dafür gemacht, Python zu kompilieren oder es in eine ausführbare Datei umzuwandeln.

Verwenden Sie py2exe , um eine EXE- Datei zu erstellen .

Verwenden Sie zum Erstellen eines Pakets für Mac oder Linux den Prozess des regulären Verpackungssystems, da ein Skriptsprachenprogramm in Unix env nichts Spezifisches enthält.

e-satis
quelle
2
Nun, es erlaubt mir, meine .py-Dateien in .so-Dateien umzuwandeln. Siehe das obige Skript, das ich verwende. Enthalten die .so-Dateien keinen ausführbaren Code?
Mozza
Es ist nicht der Zweck. Cython dient zum Kompilieren von C / C ++ - Python-Erweiterungen und nicht zum Ausführen von Python-Skripten in ausführbare Dateien.
E-
9
Fehlinformationen. Es gibt cython --embedwelche, die ausführbare Dateien mit eingebettetem Python erzeugen können.
Nudzo
Die resultierende ausführbare Datei hängt weiterhin von libpython ab, es sei denn, Sie verknüpfen sie statisch. Außerdem wird nicht eine ausführbare Datei aus all Ihren Dateien erstellt, sondern eine ausführbare Datei aus Ihrem Einstiegspunkt.
E-Satis
2
@ e-satis Ja, die ausführbare Datei wird dynamisch mit der Version von libpython verknüpft, gegen die sie zu diesem Zeitpunkt kompiliert wurde. Was ist das Problem? Wenn es sich um Linux handelt und Sie planen, Ihre Anwendung zu verteilen, packen Sie sie einfach in das Linux-Verteilungsformat, auf das Sie abzielen - genau wie jedes andere Binärpaket. Beispiel: myapp_1_wheezy_amd64.deb wäre Ihre kompilierte Python-App, die für diese Distribution entweder mit python2 oder python3 verknüpft ist. Für Windows geben Sie einfach die erforderliche Python an. Auch hier sehe ich das Problem oder den Einwand nicht.
Broken Man