Skompiluj główny program w Pythonie za pomocą Cythona

81

Mam program w Pythonie 2.6, który może załadować moduły Pythona skompilowane do plików .so przy użyciu Cythona. Użyłem Cythona do skompilowania modułów .py do plików .so i wszystko działa dobrze.

Oto plik setup.py, którego używam z Cythonem:

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
)

Więc wiem, że mogę skompilować moduły Pythona za pomocą Cythona (wydaje mi się, że Cython tworzy pliki „C” z moich plików Pythona, a następnie je kompiluje), ale czy mogę skompilować mój główny program w Pythonie do czegoś, co mogę wykonać na platformie Linux? Jeśli tak, to przykład wiersza poleceń Cythona byłby mile widziany. Dzięki.

mozza
źródło
4
Czy któreś z tych odpowiedzi były przydatne? Czy to działa? Jeśli tak, proszę przyjąć odpowiedź
Mike Pennington,
3
Wątpię, żeby to kiedykolwiek zostało zaznaczone - użytkownik był ostatnio widziany dzień po dacie edycji pytania.
Broken Man

Odpowiedzi:

152

Wbrew temu, co Adam Matan a inni twierdzą, to może faktycznie utworzyć pojedynczy wykonywalny plik binarny używając Cython, z pliku czystego Python (.py).

Tak, Cython ma być używany zgodnie z opisem - jako sposób na uproszczenie pisania modułów rozszerzeń C / C ++ dla środowiska wykonawczego CPython python.

Ale, jak nudzo nawiązuje do tego komentarza , możesz użyć --embedprzełącznika w wierszu poleceń.

Oto niezwykle prosty przykład. Robię to ze stacji roboczej Debian Sid, używając python3 i cython3.

Upewnij się, że masz wcześniej zainstalowane pakiety python-dev lub python3-dev .

1) Utwórz bardzo prosty program w Pythonie o nazwie hello.py

$ cat hello.py

print ("Witaj świecie!")

2) Użyj Cythona, aby skompilować swój program w Pythonie do C ...

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

3) Użyj GCC, aby skompilować hello.c do pliku wykonywalnego o nazwie hello ...

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

4) Otrzymujesz plik o nazwie hello ...

$ file witaj

witam: ELF 64-bitowy plik wykonywalny LSB, x86-64, wersja 1 (SYSV), połączony dynamicznie (używa bibliotek współdzielonych), dla systemu GNU / Linux 2.6.32, identyfikator kompilacji [sha1] = 006f45195a26f1949c6ed051df9cbd4433e1ac23, nierozciągnięty

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

W tym przypadku plik wykonywalny jest dynamicznie powiązany z Pythonem 3.3 w moim systemie Debian.

5) biegnij cześć ...

$ ./hello

Witaj świecie!

Jak widać, przy użyciu tej metody można w zasadzie użyć Cythona do konwersji czystych aplikacji Python na wykonywalny, skompilowany kod obiektowy.

Używam tej metody do znacznie bardziej złożonych aplikacji - na przykład w pełni rozwiniętej aplikacji Python / PySide / Qt.

W przypadku różnych wersji Pythona dostosowujesz gcc -Ii -lprzełączniki do swoich potrzeb.

Następnie możesz spakować plik wykonywalny jako plik dystrybucyjny (.deb itp.), Bez konieczności pakowania plików Python / PySide / Qt - zaletą jest to, że Twoja aplikacja powinna nadal działać nawet po aktualizacji dystrybucji do tego samego wersje Pythona itp. w tej dystrybucji.

Załamany człowiek
źródło
czy ta metoda osadzania może służyć do generowania biblioteki dynamicznej zamiast pliku wykonywalnego?
denfromufa
5
Nie kompiluje modułów do pliku wykonywalnego. Czy można mieć przenośny plik wykonywalny, tj. Każdy moduł, który został zaimportowany w kodzie źródłowym, zostałby wkompilowany w ten plik wykonywalny. @BrokenMan
Devesh Saini,
1
@DeveshSaini Nie spędziłem czasu na próbach rozwiązania tego problemu. Jedynym sposobem, w jaki udało mi się uzyskać pełną aplikację Python + Pyside do skompilowania jak powyżej, było stworzenie programu w normalny sposób - wiele instrukcji include <mymodule> + testowanie za pomocą interpretera. Następnie, gdy wszystko jest gotowe, ręcznie wklejam cały dołączony kod i komentuję odpowiednie instrukcje include, które zastąpiły. Tak, jest to niepożądane, ale jak powiedziałem na początku, nie spędziłem czasu, aby zobaczyć, jak mogę skompilować tylko główną procedurę i połączyć ze sobą dołączone moduły.
Broken Man
3
A co ze statycznym łączeniem libpythona?
James Mills
4
Dla Pythona 2.7 cython --embed -o /tmp/a.c a.pyigcc -Os -I /usr/include/python2.7 -o /tmp/a/tmp/a.c -lpython2.7 -lpthread -lm -lutil -ldl
dsaydon
17

Spójrz na odpowiedzi na pytanie Czy Cython może skompilować się do pliku EXE? które, w przeciwieństwie do wszystkich innych odpowiedzi tutaj, mówią, że tak, można skompilować do pliku wykonywalnego.

Linki w Embedding Cython wydają się być dobrym miejscem do rozpoczęcia, ale nie jest to głównym celem Cythona, więc nie wiem, jak proste byłoby to.

Scott Griffiths
źródło
1
Dzięki za linki. Podejrzewam również, że jest to możliwe, ponieważ używam Pythona do tworzenia plików .so, które zawierają kod wykonywalny.
mozza
4

Nie wiem, czy to pomoże, czy nie, ale Nudzo ma rację. Możesz to pobrać, cython --embed -o main.o main.pya następnie próbuję skompilować wynik za pomocą cl / EHsc

Jake Cook
źródło
-21

Nie możesz, Cython nie jest stworzony do kompilowania Pythona ani przekształcania go w plik wykonywalny.

Aby utworzyć plik .exe, użyj py2exe .

Aby utworzyć pakiet dla systemu Mac lub Linux, użyj standardowego procesu pakowania, ponieważ nie ma nic szczególnego na temat programu języka skryptowego w środowisku Unix env.

e-satis
źródło
2
Cóż, pozwala mi zamienić moje pliki .py na pliki .so. Zobacz powyższy skrypt, którego używam. Czy pliki .so nie zawierają kodu wykonywalnego?
mozza
Nie o to chodzi. Cython służy do kompilowania rozszerzeń języka C / C ++ Python, a nie do przekształcania skryptów Pythona w pliki wykonywalne.
e-satis
10
Mylna informacja. Są takie, cython --embedktóre mogą tworzyć pliki wykonywalne z osadzonym Pythonem.
nudzo
Wynikowy plik wykonywalny nadal zależy od libpythona, chyba że połączysz go statycznie. Ponadto nie utworzy jednego pliku wykonywalnego ze wszystkich plików, ale jeden plik wykonywalny z punktu wejścia.
e-satis
2
@ e-satis Tak, plik wykonywalny zostanie dynamicznie powiązany z wersją libpython, dla której został skompilowany w tym czasie. W czym problem? Jeśli jest przeznaczony dla systemu Linux i planujesz dystrybucję aplikacji, po prostu spakuj ją do dowolnego docelowego formatu dystrybucji systemu Linux - tak jak każdy inny pakiet binarny. np. myapp_1_wheezy_amd64.deb byłaby twoją skompilowaną aplikacją Pythona połączoną z python2 lub python3 dla tej dystrybucji. W przypadku systemu Windows wystarczy podać wymagany język Python. Ponownie nie widzę tutaj problemu ani zarzutu.
Broken Man,