Frage

Wie machbar wäre es Python zu kompilieren (möglicherweise über eine Zwischen C-Darstellung) in Maschinencode?

Vermutlich müßte es zu einer Python-Laufzeitbibliothek verknüpfen, und alle Teile der Python-Standardbibliothek, den Python selbst waren (und verknüpfen in) müssten kompiliert werden.

Auch müßten Sie die Python-Interpreter zu bündeln, wenn Sie dynamische Auswertung von Ausdrücken tun wollen, aber vielleicht eine Teilmenge von Python, die dies nicht zuließ wäre immer noch nützlich sein.

Wäre es keine Geschwindigkeit und / oder Vorteile der Speichernutzung? Vermutlich wäre die Startzeit des Python-Interpreter eliminiert werden (obwohl Shared Libraries noch beim Start geladen müßte).

War es hilfreich?

Lösung

Versuchen

ShedSkin Python-to-C ++ Compiler, aber es ist bei weitem nicht perfekt. Auch gibt es Psyco - Python JIT wenn nur Speedup benötigt wird. Aber meiner Meinung nach ist dies nicht der Mühe wert. Für geschwindigkeitskritischen Teile des Codes würde beste Lösung sein, sie ++ Erweiterungen wie C / C zu schreiben.

Andere Tipps

Wie @ Greg Hewgill es sagt, es gibt gute Gründe, warum dies nicht immer möglich ist. Allerdings sind bestimmte Arten von Code (wie sehr algorithmischen Code) in „echten“ Maschinencode umgewandelt werden.

Es gibt mehrere Möglichkeiten:

  • Verwenden Sie Psyco , die dynamisch Maschinencode aussendet. Sie sollten sorgfältig auswählen, welche Methoden / Funktionen zu konvertieren, though.
  • Verwenden Sie Cython , die eine Python- wie Sprache, die in eine Python kompiliert C-Erweiterung
  • Verwenden Sie PyPy , die einen Übersetzer von RPython hat (eine eingeschränkte Teilmenge von Python, das tut nicht einige der „dynamischen“ Eigenschaften von Python) bis C oder LLVM unterstützen.
    • PyPy ist noch sehr experimentell
    • nicht alle Erweiterungen werden anwesend sein

Danach werden Sie eine der vorhandenen Pakete verwenden können (Gefrier, Py2exe, PyInstaller) alles in einen binären zu setzen.

Alles in allem: Es gibt keine allgemeingültige Antwort für Ihre Frage. Wenn Sie Python-Code, der Performance-kritisch ist, versuchen, so viel eingebaute Funktionalität wie möglich zu nutzen (oder stellen Sie eine Frage „Wie kann ich eine Python-Code schneller zu machen“). Wenn das nicht hilft, versuchen Sie den Code und die Portierung auf C (oder Cython) und verwenden Sie die Erweiterung zu identifizieren.

py2c ( http://code.google.com/p/py2c ) können Python-Code konvertieren c / c ++ Ich bin der Solo-Entwickler von py2c.

Nuitka ist ein Python C ++ Compiler, der gegen libpython verbindet. Es scheint ein relativ neues Projekt. Der Autor behauptet, eine Geschwindigkeitsverbesserung über CPython auf der pystone Benchmark.

PyPy ist ein Projekt Python in Python neu zu implementieren, Kompilierung nativen Code als eine der Umsetzungsstrategien unter Verwendung von ( andere ist eine VM mit JIT, JVM, etc.). Ihre kompilierte C-Versionen laufen langsamer als CPython im Durchschnitt aber viel schneller für einige Programme.

Shedskin ist eine experimentelle Python-to-C ++ Compiler.

Pyrex speziell ist eine Sprache, die für Erweiterungsmodule Python zu schreiben. Es wurde entwickelt, um die Lücke zwischen den schönen, auf hohem Niveau, einfach zu bedienende Welt von Python und die chaotische, Low-Level-Welt von C zu überbrücken.

Pyrex ist eine Teilmenge der Python-Sprache, die kompiliert C, von dem Typ durchgeführt, die ersten Listenkomprehensionen für Python gebaut. Es war vor allem für den Bau Wrapper entwickelt, kann aber in einem allgemeineren Kontext verwendet werden. Cython ist eine aktive Gabel von Pyrex beibehalten.

Dies könnte auf den ersten Blick sinnvoll erscheinen, aber es gibt eine Menge von gewöhnlichen Dinge in Python, die nicht direkt auf eine C-Darstellung ohne Durchführung über einen großen Teil der Python-Laufzeitunterstützung abbildbar sind. Zum Beispiel kommt Duck Typing in dem Sinne. Viele Funktionen in Python, die Eingabe zu lesen, eine Datei nehmen oder dateiähnliche Objekt, solange sie bestimmte Operationen unterstützt, zB. read () oder Readline- (). Wenn Sie darüber nachdenken, was würde es diese Art von Unterstützung für C abzubilden, beginnen Sie genau die Art von Dingen, sich vorzustellen, dass die Python-Laufzeitsystem bereits der Fall ist.

Es gibt Dienstprogramme wie py2exe , die ein Python-Programm und Laufzeit in einer einzigen ausführbaren bündeln (so weit wie möglich).

Einige zusätzliche Hinweise:

Jython hat einen Compiler Targeting JVM-Bytecode. Der Bytecode ist voll dynamisch, ebenso wie die Sprache Python selbst! Sehr cool. (Ja, so Greg Hewgill Antwort anspielt, der Bytecode funktioniert die Jython Laufzeit verwenden, und so muss die Jython-JAR-Datei mit Ihrer Anwendung verteilt werden.)

Psyco ist eine Art von Just-in-Time-Compiler (JIT): dynamische Compiler für Python, läuft Code 2-100 mal schneller, aber es braucht viel Speicher.

Kurz gesagt:. Es Ihre vorhandenen Python Software viel schneller laufen, ohne eine Änderung in der Quelle, aber es nicht kompiliert Code auf die gleiche Weise eines C-Compiler würde zum Objekt

Die Antwort ist „Ja, es ist möglich“. Sie könnten Python-Code nehmen und es in den entsprechenden C-Code zu kompilieren versuchen, die CPython API. In der Tat, verwendet ein Python2C Projekt zu sein, die nur das tat, aber ich habe nicht darüber in vielen Jahren gehört (zurück in den Python 1,5 Tage, wenn ich sah es zuletzt.)

Sie könnten versuchen, den Python-Code in nativen C so viel wie möglich zu übersetzen, und zurück in der CPython API fallen, wenn Sie tatsächlich Python Funktionen benötigen. Ich habe liebäugelt mit dieser Idee selbst den letzten Monat oder zwei. Es ist jedoch eine Menge Arbeit, und eine enorme Menge an Python Funktionen sind sehr schwer in C zu übersetzen: verschachtelte Funktionen, Generatoren, alles andere als einfache Klassen mit einfachen Methoden, etwas zu modifizieren Modul Globals Einbeziehung von außerhalb des Moduls, etc. etc.

Dies lässt sich nicht kompilieren Python in Maschinencode. Aber erlaubt eine gemeinsame Bibliothek zu erstellen Python-Code aufzurufen.

Wenn das, was Sie suchen eine einfache Möglichkeit, ohne sie auf execp Sachen Python-Code von C auszuführen. Sie könnten eine gemeinsame Bibliothek von Python-Code generieren mit ein paar Anrufe zu verpackenden Python Einbettungs API . Nun, die Anwendung ist eine gemeinsame Bibliothek, ein .so, die Sie in vielen anderen Bibliotheken / Anwendungen verwenden können.

Hier ist ein einfaches Beispiel, das eine gemeinsame Bibliothek zu erstellen, dass Sie mit einem C-Programm verknüpfen. Die gemeinsam genutzte Bibliothek führt Python-Code.

Die Python-Datei, die ausgeführt wird, ist 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

Sie können es versuchen, mit python2 -c "import pythoncalledfromc; pythoncalledfromc.main('HELLO'). Es wird ausgegeben:

python is called from c
string sent by «c» code is:
HELLO
end of «c» code input

Die gemeinsam genutzte Bibliothek wird durch die folgende von callpython.h definiert werden:

#ifndef CALL_PYTHON
#define CALL_PYTHON

void callpython_init(void);
int callpython(char ** arguments);
void callpython_finalize(void);

#endif

Die zugehörige callpython.c ist:

// 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();
}

Sie können es mit dem folgenden Befehl kompilieren:

gcc `python2.7-config --ldflags` `python2.7-config --cflags` callpython.c -lpython2.7 -shared -fPIC -o callpython.so

Erstellen Sie eine Datei namens callpythonfromc.c, die Folgendes enthält:

#include "callpython.h"

int main(void) {
  char * example = "HELLO";
  callpython_init();
  callpython(&example);
  callpython_finalize();
  return 0;
}

Kompilieren sie und führen Sie:

gcc callpythonfromc.c callpython.so -o callpythonfromc
PYTHONPATH=`pwd` LD_LIBRARY_PATH=`pwd` ./callpythonfromc

Dies ist ein sehr einfaches Beispiel. Es kann funktionieren, aber abhängig von der Bibliothek könnte es immer noch schwierig sein, C-Datenstrukturen zu Python serialisiert und von Python zu C. Den Dingen kann etwas automatisiert werden ...

Nuitka könnte sein, hilfreich.

Auch gibt es numba aber beide wollen nicht tun, was Sie genau wollen. einen C-Header aus Python-Code zu erzeugen ist möglich, aber nur, wenn Sie das, wie Sie wandeln die Python-Typen C-Typen angeben oder diese Informationen entnehmen können. Siehe Python astroid für einen Python ast Analysator.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top