Czy istnieje sposób na skompilowanie aplikacji Pythona do statycznej postaci binarnej?

86

To, co próbuję zrobić, to wysłać mój kod na zdalny serwer, na którym może być zainstalowana inna wersja języka Python i / lub może nie mieć pakietów wymaganych przez moją aplikację.

W tej chwili, aby osiągnąć taką przenośność, muszę zbudować relokowalny virtualenv z interpreterem i kodem. Takie podejście ma pewne problemy (na przykład, musisz ręcznie skopiować kilka bibliotek do swojego virtualenv, ponieważ --always-copynie działa zgodnie z oczekiwaniami) i ogólnie powolne.

Istnieje (w teorii) sposób na statyczne zbudowanie samego Pythona.

Zastanawiam się, czy mógłbym spakować interpreter z moim kodem do jednego pliku binarnego i uruchomić moją aplikację jako moduł. Coś takiego: ./mypython -m myapp runlub ./mypython -m gunicorn -c ./gunicorn.conf myapp.wsgi:application.

roboslone
źródło
Czy masz na myśli coś takiego jak cx_freeze?
TigerhawkT3
@ TigerhawkT3, do dzisiaj nie słyszałem o cx_freeze. Przejrzałem dokumenty, wydaje mi się, że tego właśnie chcę, ale nie udało mi się zbudować na Ubuntu 12.04.5 z python3.5.1. Szukam alternatywy, dzięki za kopnięcie we właściwym kierunku.
roboslone
Niestety, pyinstaller nie działa z Django 1.9, a py2app / py2exe nie obsługuje linuxa :(
roboslone
2
jeśli cx_Freeze i pyinstaller nie działają, wciąż jest nadzieja. Możesz utworzyć pakiety dla dystrybucji docelowych, które rozwiążą wszystkie zależności związane z instalacją. A może użyj czegoś takiego jak docker, aby uruchomić aplikację.
KeatsPeeks,
1
inne opcje to nuitka i cython
denfromufa

Odpowiedzi:

121

Istnieją dwa sposoby rozwiązania problemu

  1. Użyj konstruktora statycznego, takiego jak zamrażanie lub pyinstaller, lubpy2exe
  2. Skompiluj za pomocą cython

Wyjaśnię, jak możesz to zrobić za pomocą drugiej, ponieważ pierwsza metoda nie jest wieloplatformowa i wersja, i została wyjaśniona w innych odpowiedziach. Ponadto używanie programów takich jak pyinstaller zwykle powoduje ogromne rozmiary plików, przy czym użycie cythona spowoduje powstanie pliku o rozmiarze KB

Najpierw zainstaluj cython. Następnie zmień nazwę pliku Pythona (powiedzmy test.py) na .pyxplik

sudo pip install cython
mv test.py test.pyx

Następnie możesz użyć cythonrazem z GCC do skompilowania go ( cythongeneruje plik C z pliku Python .pyx, a następnie GCC kompiluje plik C)

(w odniesieniu do 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

UWAGA : W zależności od wersji Pythona może być konieczna zmiana ostatniego polecenia. Aby dowiedzieć się, której wersji Pythona używasz, po prostu użyj

$ python -V

Będziesz mieć teraz plik binarny „test”, którego szukasz

Inne uwagi :

  1. Cython jest używany do używania definicji zmiennych typu C do statycznej alokacji pamięci w celu przyspieszenia programów w Pythonie. Jednak w twoim przypadku nadal będziesz używać tradycyjnych definicji Pythona.
  2. Jeśli używasz dodatkowych bibliotek (jak opencvna przykład), może być konieczne dostarczenie im katalogu za pomocą, -La następnie określenie nazwy biblioteki używanej -lwe flagach GCC. Więcej informacji na ten temat można znaleźć w sekcji Flagi GCC
RS Nikhil Krishna
źródło
20
Cześć, co jeśli moja aplikacja obejmuje wiele plików. To podejście wydaje się kompilować tylko bieżący skrypt, a nie wszystkie zależności Pythona.
RChat
2
nie ma potrzeby zmieniania nazwy pliku Pythona (powiedzmy test.py) na pyx w tej chwili
iMath
3
To było dla mnie bardzo pomocne. Aby odpowiedzieć na pytanie dotyczące wielu plików, możesz użyć cythonize: cythonize -i file_0.py [...] file_n.pydla wszystkich modułów Pythona, a następnie cython main_file.py --embeddla głównego skryptu. Otrzymasz pliki wykonywalne i .so (.dll, .dylib w zależności od systemu operacyjnego), których możesz używać razem jako samodzielne rozwiązanie.
afp
Otrzymuję komunikat „Brak modułów o nazwie kodowania”. Dowiedziałem się, że potrzebuję pewnych plików z instalacji Pythona. Jednak mój system docelowy nie ma języka Python. Proszę pomóż.
abhiarora
9

Możesz chcieć zbadać Nuitka . Pobiera kod źródłowy Pythona i konwertuje go na wywołania API C ++. Następnie kompiluje się do wykonywalnego pliku binarnego (ELF w systemie Linux). Istnieje już od kilku lat i obsługuje szeroką gamę wersji Pythona.

Prawdopodobnie uzyskasz również poprawę wydajności, jeśli go użyjesz. Zalecana.

Prakhar Agarwal
źródło
Nie mogłem znaleźć żadnych informacji o używaniu Nuitka z Django. Czy masz przypadkiem takie doświadczenie?
roboslone
@roboslone, Prakhar Agarwal Cython bardzo dobrze obsługuje zewnętrzne biblioteki w porównaniu do statycznego kreatora Nuitka PyPy. Na przykład z linku na końcu tego komentarza wynika, że ​​„ludzie używają Cythona, ponieważ pomaga im to w rozwiązaniu problemu. Oznacza to, że chcą połączyć się z zewnętrznymi bibliotekami innymi niż Python z kodu Pythona lub chcą mieć możliwość ręcznie zoptymalizować ich kod lub jedno i drugie. ”, link to blog.behnel.de/posts/indexp241.html
RS Nikhil Krishna
1
RS Nikhil Krishna, nie próbuję przyspieszyć mojego kodu, próbuję wysłać go w jednym pliku binarnym z wbudowanym interpretera Pythona.
roboslone
No dobrze. Myślałem, że chcesz go powiązać z jakąś zewnętrzną biblioteką. Mój błąd.
RS Nikhil Krishna
1

Jeśli korzystasz z komputera Mac, możesz użyć py2app, aby utworzyć pakiet .app, który uruchamia aplikację Django po dwukrotnym kliknięciu.

Opisałem, jak połączyć Django i CherryPy w taki pakiet na https://moosystems.com/articles/14-distribute-django-app-as-native-desktop-app-01.html

W artykule używam pywebview do wyświetlania Twojej strony Django w lokalnym oknie aplikacji.

André Aulich
źródło
Moja aplikacja działa głównie na Linuksie, więc py2app nie działa
roboslone
Chociaż artykuł używa py2app, można to zrobić również za pomocą pyinstaller.
André Aulich
0

Opcje zamrażania:

Jednak serwer docelowy powinien mieć żądane środowisko -> powinieneś być w stanie je „stworzyć”. Jeśli tak się nie stanie, powinieneś zbudować oprogramowanie tak, aby pasowało do środowiska.

Znalazłem ten przydatny przewodnik, jak zainstalować niestandardową wersję Pythona na virtualenv, zakładając, że masz dostęp do ssh: https://stackoverflow.com/a/5507373/5616110

W virtualenv powinieneś być w stanie zainstalować wszystko za pomocą pip i nie powinieneś martwić się o uprawnienia sudo. Oczywiście posiadanie ich i dostęp do menedżera pakietów, takiego jak apt, znacznie ułatwia wszystko.

iScrE4m
źródło
Używam już virtualenv, tak nie jest. Moje pytanie dotyczy statycznie skompilowanego Pythona z wymaganymi modułami i aplikacjami.
roboslone
Następnie musisz go zamrozić, nie ma innego wyjścia.
iScrE4m