Jak wykonalne byłoby skompilowanie Pythona (prawdopodobnie poprzez pośrednią reprezentację C) do kodu maszynowego?
Prawdopodobnie musiałoby to być linkowane do biblioteki wykonawczej Pythona, a wszelkie części standardowej biblioteki Pythona, które same byłyby Pythonem, również musiałyby zostać skompilowane (i połączone).
Ponadto, jeśli chciałbyś przeprowadzić dynamiczną ocenę wyrażeń, musiałbyś spakować interpreter Pythona, ale być może podzbiór Pythona, który na to nie pozwalał, byłby nadal przydatny.
Czy zapewniłoby to jakieś korzyści związane z szybkością i / lub wykorzystaniem pamięci? Przypuszczalnie czas uruchamiania interpretera Pythona zostałby wyeliminowany (chociaż biblioteki współdzielone nadal wymagałyby ładowania podczas uruchamiania).
źródło
Odpowiedzi:
Wypróbuj kompilator ShedSkin Python-to-C ++, ale jest daleki od doskonałości. Istnieje również Psyco - Python JIT, jeśli potrzebne jest tylko przyspieszenie. Ale IMHO to nie jest warte wysiłku. W przypadku części kodu o krytycznym znaczeniu dla szybkości najlepszym rozwiązaniem byłoby zapisanie ich jako rozszerzeń C / C ++.
źródło
Jak mówi @Greg Hewgill, istnieją dobre powody, dla których nie zawsze jest to możliwe. Jednak niektóre rodzaje kodu (jak kod bardzo algorytmiczny) można przekształcić w „prawdziwy” kod maszynowy.
Istnieje kilka opcji:
Następnie możesz użyć jednego z istniejących pakietów (freeze, Py2exe, PyInstaller), aby umieścić wszystko w jednym pliku binarnym.
Podsumowując: nie ma ogólnej odpowiedzi na twoje pytanie. Jeśli masz kod w Pythonie, który jest krytyczny dla wydajności, spróbuj użyć jak największej liczby wbudowanych funkcji (lub zadaj pytanie „Jak przyspieszyć mój kod w Pythonie”). Jeśli to nie pomoże, spróbuj zidentyfikować kod i przenieś go do C (lub Cython) i użyj rozszerzenia.
źródło
py2c ( https://github.com/pradyun/Py2C ) potrafi konwertować kod Pythona do c / c ++ Jestem samodzielnym programistą py2c.
źródło
Nuitka to kompilator Pythona do C ++, który łączy się z libpythonem. Wydaje się, że jest to stosunkowo nowy projekt. Autor twierdzi, że w teście porównawczym pystone poprawia prędkość w stosunku do CPython.
źródło
PyPy to projekt reimplementacji Pythona w Pythonie, przy użyciu kompilacji do kodu natywnego jako jednej ze strategii implementacji (inne to maszyny wirtualne z JIT, używanie JVM itp.). Ich skompilowane wersje C działają średnio wolniej niż CPython, ale w przypadku niektórych programów znacznie szybciej.
Shedskin to eksperymentalny kompilator Pythona do C ++.
Pyrex to język zaprojektowany specjalnie do pisania modułów rozszerzeń Pythona. Został zaprojektowany, aby wypełnić lukę między przyjemnym, wysokopoziomowym, łatwym w użyciu światem Pythona a niechlujnym, niskopoziomowym światem C.
źródło
Pyrex jest podzbiorem języka Python, który kompiluje się do C, wykonanym przez faceta, który jako pierwszy zbudował listy składane dla Pythona. Został opracowany głównie do budowania opakowań, ale może być używany w bardziej ogólnym kontekście. Cython jest bardziej aktywnie utrzymywanym widelcem pyrexu.
źródło
Dodatkowe odniesienia:
https://github.com/dropbox/pyston to kompilator JIT dla Pythona opracowany przez Dropbox
http://pythran.readthedocs.io/ jest tłumaczem języka Python na C ++ w czasie kompilacji do obliczeń naukowych
https://github.com/cosmo-ethz/hope to tłumacz JIT z Pythona na C ++ do obliczeń naukowych
źródło
Jython ma kompilator przeznaczony dla kodu bajtowego JVM. Kod bajtowy jest w pełni dynamiczny, podobnie jak sam język Python! Bardzo fajny. (Tak, jak sugeruje odpowiedź Grega Hewgilla, kod bajtowy korzysta ze środowiska wykonawczego Jython, więc plik jar Jython musi być rozpowszechniany wraz z aplikacją).
źródło
Psyco jest rodzajem kompilatora just-in-time (JIT): kompilator dynamiczny dla Pythona, uruchamia kod 2-100 razy szybciej, ale wymaga dużo pamięci.
Krótko mówiąc: uruchamia istniejące oprogramowanie Python znacznie szybciej, bez zmian w kodzie źródłowym, ale nie kompiluje się do kodu obiektowego w taki sam sposób, jak kompilator C.
źródło
Odpowiedź brzmi: „Tak, jest to możliwe”. Możesz wziąć kod Pythona i spróbować skompilować go do odpowiednika kodu C za pomocą CPython API. W rzeczywistości istniał kiedyś projekt Python2C, który właśnie to robił, ale nie słyszałem o tym od wielu lat (w Pythonie 1.5 dni to ostatni raz.)
Możesz próbować przetłumaczyć kod Pythona na natywne C tak bardzo, jak to możliwe, i wrócić do interfejsu API CPython, gdy potrzebujesz rzeczywistych funkcji Pythona. Sam bawiłem się tym pomysłem przez ostatni miesiąc lub dwa. Jest to jednak bardzo dużo pracy, a ogromna ilość funkcji Pythona jest bardzo trudna do przetłumaczenia na C: funkcje zagnieżdżone, generatory, wszystko oprócz prostych klas z prostymi metodami, wszystko, co wiąże się z modyfikowaniem globalnych modułów spoza modułu itp. itp.
źródło
To nie kompiluje Pythona do kodu maszynowego. Ale pozwala stworzyć współdzieloną bibliotekę do wywoływania kodu Pythona.
Jeśli szukasz łatwego sposobu na uruchomienie kodu Pythona z poziomu C bez polegania na plikach execp. Możesz wygenerować bibliotekę współdzieloną z kodu Pythona opakowanego w kilka wywołań API osadzania w Pythonie . Cóż, aplikacja jest biblioteką współdzieloną, tak że można jej używać w wielu innych bibliotekach / aplikacjach.
Oto prosty przykład, który tworzy bibliotekę współdzieloną, którą można połączyć z programem C. Biblioteka współdzielona wykonuje kod Pythona.
Plik Pythona, który zostanie wykonany, to
pythoncalledfromc.py
:# -*- encoding:utf-8 -*- # this file must be named "pythoncalledfrom.py" def main(string): # args must a string print "python is called from c" print "string sent by «c» code is:" print string print "end of «c» code input" return 0xc0c4 # return something
Możesz to wypróbować
python2 -c "import pythoncalledfromc; pythoncalledfromc.main('HELLO')
. Wyświetli:python is called from c string sent by «c» code is: HELLO end of «c» code input
Biblioteka współdzielona zostanie zdefiniowana przez
callpython.h
:#ifndef CALL_PYTHON #define CALL_PYTHON void callpython_init(void); int callpython(char ** arguments); void callpython_finalize(void); #endif
Powiązane
callpython.c
to:// gcc `python2.7-config --ldflags` `python2.7-config --cflags` callpython.c -lpython2.7 -shared -fPIC -o callpython.so #include <stdlib.h> #include <stdio.h> #include <string.h> #include <python2.7/Python.h> #include "callpython.h" #define PYTHON_EXEC_STRING_LENGTH 52 #define PYTHON_EXEC_STRING "import pythoncalledfromc; pythoncalledfromc.main(\"%s\")" void callpython_init(void) { Py_Initialize(); } int callpython(char ** arguments) { int arguments_string_size = (int) strlen(*arguments); char * python_script_to_execute = malloc(arguments_string_size + PYTHON_EXEC_STRING_LENGTH); PyObject *__main__, *locals; PyObject * result = NULL; if (python_script_to_execute == NULL) return -1; __main__ = PyImport_AddModule("__main__"); if (__main__ == NULL) return -1; locals = PyModule_GetDict(__main__); sprintf(python_script_to_execute, PYTHON_EXEC_STRING, *arguments); result = PyRun_String(python_script_to_execute, Py_file_input, locals, locals); if(result == NULL) return -1; return 0; } void callpython_finalize(void) { Py_Finalize(); }
Możesz go skompilować za pomocą następującego polecenia:
gcc `python2.7-config --ldflags` `python2.7-config --cflags` callpython.c -lpython2.7 -shared -fPIC -o callpython.so
Utwórz plik o nazwie,
callpythonfromc.c
który zawiera następujące elementy:#include "callpython.h" int main(void) { char * example = "HELLO"; callpython_init(); callpython(&example); callpython_finalize(); return 0; }
Skompiluj i uruchom:
gcc callpythonfromc.c callpython.so -o callpythonfromc PYTHONPATH=`pwd` LD_LIBRARY_PATH=`pwd` ./callpythonfromc
To jest bardzo podstawowy przykład. Może działać, ale w zależności od biblioteki może być nadal trudno serializować struktury danych C do Pythona iz Pythona do C. Wszystko można nieco zautomatyzować ...
Nuitka może być pomocna.
Jest też numba, ale obaj nie mają na celu robienia dokładnie tego, co chcesz. Generowanie nagłówka C z kodu Pythona jest możliwe, ale tylko wtedy, gdy określisz sposób konwersji typów Python na typy C lub możesz wywnioskować te informacje. Zobacz Python astroid dla analizatora Python ast.
źródło