Gibt es eine Möglichkeit, eine Python-Anwendung in eine statische Binärdatei zu kompilieren?

83

Ich versuche, meinen Code an einen Remote-Server zu senden, auf dem möglicherweise eine andere Python-Version installiert ist und / oder auf dem für meine App möglicherweise keine Pakete erforderlich sind.

Um eine solche Portabilität zu erreichen, muss ich jetzt eine verschiebbare virtuelle Umgebung mit Interpreter und Code erstellen. Dieser Ansatz weist einige Probleme auf (z. B. müssen Sie eine Reihe von Bibliotheken manuell in Ihre virtuelle Umgebung kopieren, da --always-copydies nicht wie erwartet funktioniert) und ist im Allgemeinen langsam.

Es gibt (theoretisch) eine Möglichkeit , Python selbst statisch zu erstellen.

Ich frage mich, ob ich den Interpreter mit meinem Code in eine Binärdatei packen und meine Anwendung als Modul ausführen könnte. So etwas: ./mypython -m myapp runoder ./mypython -m gunicorn -c ./gunicorn.conf myapp.wsgi:application.

Roboslone
quelle
Meinst du so etwas wie cx_freeze?
TigerhawkT3
@ TigerhawkT3, ich habe bis heute noch nie von cx_freeze gehört. Durch die Dokumente geschaut, scheint es das zu sein, was ich will, aber es baut nicht auf Ubuntu 12.04.5 mit python3.5.1 auf. Ich suche nach Alternativen, danke für den Kick in die richtige Richtung.
Roboslone
Leider funktioniert Pyinstaller nicht mit Django 1.9 und Py2app / Py2exe unterstützt kein Linux :(
Roboslone
2
Wenn cx_Freeze und pyinstaller nicht funktionieren, gibt es immer noch Hoffnung. Sie können Pakete für Ihre Zieldistribution (en) erstellen, die alle Abhängigkeiten von der Installation auflösen. Oder verwenden Sie Docker, um Ihre App auszuführen.
KeatsPeeks
1
andere Optionen sind Nuitka und Cython
Denfromufa

Antworten:

116

Es gibt zwei Möglichkeiten, wie Sie Ihr Problem lösen können

  1. Verwenden Sie einen statischen Builder wie freeze oder pyinstalleroderpy2exe
  2. Kompilieren mit cython

Ich werde erklären, wie Sie dies mit der zweiten Methode tun können, da die erste Methode nicht plattform- und versionübergreifend ist und in anderen Antworten erläutert wurde. Die Verwendung von Programmen wie pyinstaller führt normalerweise zu großen Dateigrößen, während die Verwendung von cython zu einer Datei mit einer KB-Größe führt

Installieren Sie zuerst cython. Benennen Sie dann Ihre Python-Datei (z. B. test.py) in eine .pyxDatei um

sudo pip install cython
mv test.py test.pyx

Anschließend können Sie es cythonzusammen mit GCC kompilieren ( cythongeneriert eine C-Datei aus einer Python- .pyxDatei, und GCC kompiliert dann die C-Datei).

(in Bezug auf https://stackoverflow.com/a/22040484/5714445 )

cython test.pyx --embed
gcc -Os -I /usr/include/python3.5m -o test test.c -lpython3.5m -lpthread -lm -lutil -ldl

HINWEIS : Abhängig von Ihrer Python-Version müssen Sie möglicherweise den letzten Befehl ändern. Um zu wissen, welche Python-Version Sie verwenden, verwenden Sie einfach

$ python -V

Sie haben jetzt eine Binärdatei 'test', nach der Sie suchen

Andere Dinge zu beachten :

  1. Cython wird verwendet, um Variablendefinitionen vom Typ C für die statische Speicherzuweisung zu verwenden, um Python-Programme zu beschleunigen. In Ihrem Fall verwenden Sie jedoch weiterhin traditionelle Python-Definitionen.
  2. Wenn Sie zusätzliche Bibliotheken verwenden ( opencvz. B.), müssen Sie ihnen möglicherweise das Verzeichnis mithilfe von bereitstellen -Lund dann den Namen der Bibliothek -lin den GCC-Flags angeben . Weitere Informationen hierzu finden Sie unter GCC-Flags
RS Nikhil Krishna
quelle
19
Hallo, was ist, wenn sich meine Anwendung über mehrere Dateien erstreckt? Dieser Ansatz scheint nur das aktuelle Skript und nicht alle Python-Abhängigkeiten zu kompilieren.
RChat
2
Sie müssen Ihre Python-Datei (sagen wir test.py) jetzt nicht in einen Pyx umbenennen
iMath
3
Das hat mir sehr geholfen. Um die Frage zu mehreren Dateien zu beantworten, können Sie cythonize verwenden: cythonize -i file_0.py [...] file_n.pyfür alle Ihre Python-Module und dann cython main_file.py --embedfür Ihr Hauptskript. Am Ende erhalten Sie eine ausführbare Datei und .so-Dateien (.dll, .dylib, abhängig von Ihrem Betriebssystem), die Sie zusammen als eigenständige Lösung verwenden können.
afp
Ich erhalte die Meldung "Keine Module mit dem Namen" Codierungen ". Ich habe erfahren, dass ich bestimmte Dateien für die Python-Installation benötige. Mein Zielsystem verfügt jedoch nicht über Python. Bitte helfen Sie.
Abhiarora
8

Vielleicht möchten Sie Nuitka untersuchen . Es nimmt Python-Quellcode und konvertiert ihn in C ++ - API-Aufrufe. Dann wird es in eine ausführbare Binärdatei (ELF unter Linux) kompiliert. Es gibt es schon seit einigen Jahren und es unterstützt eine Vielzahl von Python-Versionen.

Sie werden wahrscheinlich auch eine Leistungsverbesserung erhalten, wenn Sie es verwenden. Empfohlen.

Prakhar Agarwal
quelle
Ich konnte keine Informationen über die Verwendung von Nuitka mit Django finden. Haben Sie zufällig solche Erfahrungen?
Roboslone
@roboslone, Prakhar Agarwal Cython unterstützt externe Bibliotheken im Vergleich zum statischen Builder von Nuitka PyPy sehr gut. Über den Link am Ende dieses Kommentars heißt es beispielsweise: "Benutzer verwenden Cython, weil es ihnen hilft, ein Problem zu lösen. Entweder möchten sie über Python-Code eine Verbindung zu externen Nicht-Python-Bibliotheken herstellen oder sie möchten dies können." Optimieren Sie manuell ihren Code oder beides. ", der Link lautet blog.behnel.de/posts/indexp241.html
RS Nikhil Krishna
1
RS Nikhil Krishna, ich versuche nicht, meinen Code schneller zu machen, ich versuche ihn in einer Binärdatei mit Python-Interpreter zu versenden.
Roboslone
Aah okay. Ich dachte, Sie wollten es mit einer externen Bibliothek binden. Mein Fehler.
RS Nikhil Krishna
0

Einfrieroptionen:

Ihr Zielserver sollte jedoch über die gewünschte Umgebung verfügen -> Sie sollten in der Lage sein, diese zu erstellen. Wenn dies nicht der Fall ist, sollten Sie Ihre Software so erstellen, dass sie der Umgebung entspricht.

Ich habe diese praktische Anleitung zum Installieren einer benutzerdefinierten Version von Python auf einer virtuellen Umgebung gefunden, vorausgesetzt, Sie haben SSH-Zugriff: https://stackoverflow.com/a/5507373/5616110

In virtualenv sollten Sie in der Lage sein, alles zu installieren, und Sie sollten sich keine Gedanken über Sudo-Berechtigungen machen müssen. Natürlich macht es alles viel einfacher, diese zu haben und auf Paketmanager wie apt zuzugreifen.

iScrE4m
quelle
Ich verwende bereits virtualenv, dies ist nicht der Fall. Meine Frage bezieht sich auf statisch kompiliertes Python mit erforderlichen Modulen und Anwendungen.
Roboslone
Dann muss man es einfrieren, anders geht es nicht.
iScrE4m
0

Wenn Sie einen Mac verwenden, können Sie mit py2app ein .app-Bundle erstellen, mit dem Ihre Django-App gestartet wird, wenn Sie darauf doppelklicken.

Ich habe unter https://moosystems.com/articles/14-distribute-django-app-as-native-desktop-app-01.html beschrieben, wie Django und CherryPy zu einem solchen Bundle gebündelt werden

In dem Artikel verwende ich pywebview, um Ihre Django-Site in einem lokalen Anwendungsfenster anzuzeigen.

André Aulich
quelle
Meine Anwendung läuft meistens unter Linux, daher gilt py2app nicht
roboslone
Obwohl der Artikel py2app verwendet, kann er auch mit pyinstaller erstellt werden.
André Aulich