Czy jest możliwe skompilowanie Pythona do kodu maszynowego?

Jak wykonalne byłoby skompilowanie Pythona (ewentualnie poprzez pośrednią reprezentację C) do kodu maszynowego?

Prawdopodobnie wymagałoby to linkowania do biblioteki uruchomieniowej Pythona, a wszelkie części standardowej biblioteki Pythona, które same w sobie były Pythonem, również musiałyby być skompilowane (i połączone).

Również, trzeba by spakować interpreter Pythona, jeśli chcesz zrobić dynamiczną ocenę wyrażeń, ale być może podzbiór Pythona, który na to nie pozwala, nadal bądź użyteczny.

Czy zapewni to jakieś korzyści z szybkości i / lub wykorzystania pamięci? Prawdopodobnie czas uruchamiania interpretera Pythona zostałby wyeliminowany (chociaż biblioteki współdzielone nadal wymagałyby ładowania przy starcie).

Author: Andy Balaam, 2008-09-26

12 answers

Spróbuj ShedSkin kompilator 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 kluczowych dla szybkości części kodu najlepszym rozwiązaniem byłoby napisanie ich jako rozszerzeń C / C++.

 22
Author: cleg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-03 13:45:14

Jak mówi @ Greg Hewgill, istnieją dobre powody, dla których nie zawsze jest to możliwe. Jednak niektóre rodzaje kodu (jak bardzo algorytmiczny kod) można przekształcić w" prawdziwy " kod maszynowy.

Istnieje kilka opcji:

  • Użyj Psyco , które emituje kod maszynowy dynamicznie. Powinieneś jednak starannie wybrać metody / funkcje do konwersji.
  • Użyj Cython , który jest Pythonem-jak język , który jest kompilowany do Pythona C rozszerzenie
  • Użyj PyPy , który ma tłumacz z rpython (a Ograniczony podzbiór Pythona, który nie obsługuje niektórych z najbardziej "dynamicznych" cech Pythona) do C lub LLVM.
    • PyPy jest wciąż bardzo eksperymentalny
    • nie wszystkie rozszerzenia będą obecne

Następnie możesz użyć jednego z istniejących pakietów (freeze, Py2exe, PyInstaller), aby umieścić wszystko w jednym pliku binarnym.

W sumie: nie ma ogólnej odpowiedzi na twoje pytanie. Jeśli masz kod Pythona, który ma kluczowe znaczenie dla wydajności, spróbuj użyć jak największej ilości wbudowanych funkcji (lub zadaj pytanie" Jak przyspieszyć mój kod Pythona"). Jeśli to nie pomoże, spróbuj zidentyfikować kod i przenieść go do C (lub Cython) i użyć rozszerzenia.

 46
Author: Torsten Marek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-07 11:07:07

Py2c (http://code.google.com/p/py2c ) potrafi konwertować kod Pythona do c / C++ Jestem samodzielnym programistą py2c.

 16
Author: Ramchandra Apte,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-10 14:00:44

PyPy to projekt mający na celu reimplementację Pythona w Pythonie, używając kompilacji do kodu macierzystego jako jednej ze strategii implementacji (Inne to maszyna wirtualna z JIT, JVM itp.). Ich skompilowane wersje C działają wolniej niż CPython średnio, ale znacznie szybciej dla niektórych programów.

Shedskin jest eksperymentalnym kompilatorem języka Python-to-c++.

Pyrex {[2] } jest językiem specjalnie zaprojektowanym do pisania modułów rozszerzeń Pythona. Został zaprojektowany, aby wypełnić lukę między dobry, wysoki poziom, łatwy w użyciu świat Pythona i brudny, niskopoziomowy świat C.

 13
Author: pdc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-05 08:07:49

Nuitka jest kompilatorem Pythona do C++, który łączy się z libpythonem. Wydaje się, że jest to stosunkowo nowy projekt. Autor twierdzi, że Poprawa prędkości nad CPython na pystone benchmark.

 12
Author: bcattle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-09 03:52:37

Pyrex jest podzbiorem języka Python, który kompiluje się do C, wykonanym przez faceta, który jako pierwszy zbudował składnię list dla Pythona. Został opracowany głównie do budowy owijarek, ale może być stosowany w bardziej ogólnym kontekście. Cython jest aktywniej utrzymywanym widelcem pyrexu.

 10
Author: ConcernedOfTunbridgeWells,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-14 09:24:16

To może wydawać się rozsądne na pierwszy rzut oka, jednak istnieje wiele zwykłych rzeczy w Pythonie, które nie są bezpośrednio mapowane do reprezentacji C bez przenoszenia dużej części obsługi środowiska uruchomieniowego Pythona. Na przykład przychodzi mi do głowy pisanie kaczek. Wiele funkcji w Pythonie, które odczytują dane wejściowe, może przyjmować obiekt plik lub podobny do pliku, o ile obsługuje pewne operacje, np. read () lub readline (). Jeśli zastanowisz się, ile potrzeba, aby odwzorować tego typu wsparcie na C, zaczynasz aby wyobrazić sobie dokładnie takie rzeczy, które już robi Python runtime system.

Istnieją narzędzia takie jak py2exe , które łączą program Pythona i runtime w jeden plik wykonywalny (w miarę możliwości).

 9
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 09:56:08

Kilka dodatkowych odniesień:

 5
Author: serge-sans-paille,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-27 10:37:32

Jython ma kompilator kierujący kod bajtowy JVM. Kod bajtowy jest w pełni dynamiczny, podobnie jak sam język Python! Bardzo fajne. (Tak, jak wspomina odpowiedź Grega Hewgilla, kod bajtowy używa środowiska uruchomieniowego Jython, więc plik Jython jar musi być rozprowadzany wraz z aplikacją.)

 3
Author: Chris Jester-Young,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 10:00:16

Psyco jest rodzajem kompilatora just-In-time (JIT): dynamiczny kompilator dla Pythona, uruchamia kod 2-100 razy szybciej, ale potrzebuje dużo pamięci.

W skrócie: uruchamia istniejące oprogramowanie Pythona znacznie szybciej, bez zmian w źródle, ale nie kompiluje do kodu obiektowego tak, jak kompilator C.

 2
Author: Pierre-Jean Coudert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 09:59:12

Odpowiedź brzmi "tak, to możliwe". Możesz wziąć kod Pythona i spróbować skompilować go do równoważnego kodu C przy użyciu API CPython. W rzeczywistości, kiedyś był projekt Python2C, który właśnie to zrobił, ale nie słyszałem o nim od wielu lat (w Pythonie 1.5 dni to czas, kiedy ostatni raz go widziałem.)

Możesz próbować przetłumaczyć Kod Pythona na natywny Język C tak bardzo, jak to możliwe, i wrócić do API CPython, gdy potrzebujesz rzeczywistych funkcji Pythona. Bawiłem się tym. pomysł na ostatni miesiąc lub dwa. Jest to jednak strasznie dużo pracy, a ogromna ilość funkcji Pythona jest bardzo trudna do przełożenia na C: zagnieżdżone funkcje, Generatory, wszystko poza prostymi klasami z prostymi metodami, wszystko związane z modyfikowaniem globalików modułów spoza modułu, itd., itp.

 2
Author: Thomas Wouters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 10:14:09

To nie kompiluje Pythona do kodu maszynowego. Ale pozwala na utworzenie biblioteki współdzielonej do wywołania kodu Pythona.

Jeśli szukasz łatwego sposobu na uruchamianie kodu Pythona z C bez polegania na execp. Można wygenerować bibliotekę współdzieloną z kodu Pythona, owiniętą kilkoma wywołaniami do API osadzania Pythona. Cóż aplikacja jest dzielona biblioteka, an. tak, że można używać w wielu innych bibliotek / aplikacji.

Oto prosty przykład, który tworzy biblioteka współdzielona, którą można połączyć z programem w języku C. Biblioteka współdzielona wykonuje kod Pythona.

Plik Pythona, który zostanie uruchomiony 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 spróbować z python2 -c "import pythoncalledfromc; pythoncalledfromc.main('HELLO'). Wyświetli się:

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

Zwią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 skompilować go 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 po:

#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 bardzo podstawowy przykład. Może działać, ale w zależności od biblioteki nadal może być trudno serializować struktury danych C do Pythona i od Pythona do C. rzeczy mogą być nieco zautomatyzowane...

Nuitka może być pomocna.

Istnieje również numba ale obie nie dążą do tego, co chcesz dokładnie. Generowanie nagłówka C z kodu Pythona jest możliwe, ale tylko wtedy, gdy podasz jak przekonwertować typy Pythona na typy C lub można wywnioskować, że informacje. Zobacz Python astroid dla analizatora ast Pythona.

 2
Author: amirouche,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:55