Est-il possible de compiler Python en code machine?

dans quelle mesure serait-il possible de compiler Python (éventuellement via une représentation en C intermédiaire) en code machine?

on peut supposer Qu'il aurait besoin d'un lien vers une bibliothèque d'exécution Python, et toutes les parties de la bibliothèque standard Python qui sont Python elles-mêmes devraient être compilées (et reliées) aussi.

aussi, vous auriez besoin de regrouper l'interpréteur Python Si vous vouliez faire une évaluation dynamique des expressions, mais peut-être un sous-ensemble de Python qui n'a pas permis cela serait encore utile.

offrirait-il des avantages en termes de vitesse et/ou d'utilisation de la mémoire? On peut supposer que le temps de démarrage de L'interpréteur Python serait éliminé (bien que les bibliothèques partagées aient encore besoin d'être chargées au démarrage).

113
demandé sur Andy Balaam 2008-09-26 13:51:51

12 réponses

Essayer ShedSkin Python-à-compilateur C++, mais il est loin d'être parfait. Il y a aussi Psyco - Python JIT si seulement speedup est nécessaire. Mais à mon humble avis ce n'est pas la valeur de l'effort. Pour les parties critiques du code, la meilleure solution serait de les écrire comme des extensions C/C++.

22
répondu cleg 2017-07-03 13:45:14

comme le dit @Greg Hewgill, il y a de bonnes raisons pour lesquelles ce n'est pas toujours possible. Cependant, certains types de code (comme le code très algorithmique) peuvent être transformés en "vrai" code machine.

il y a plusieurs options:

  • utiliser Psyco , qui émet un code machine dynamiquement. Vous devez choisir soigneusement les méthodes/fonctions de conversion.
  • Utiliser Cython , qui est un Python - comme langage qui est compilé dans une extension Python C
  • Use PyPy , qui a un traducteur de RPython (un restricted subset de Python qui ne supporte pas certaines des fonctionnalités les plus" dynamiques " de Python) vers C ou LLVM.
    • PyPy est encore très expérimental
    • toutes les extensions ne seront pas présentes

après cela, vous pouvez utiliser l'un des paquets existants (freeze, Py2exe, PyInstaller) pour tout mettre dans un binaire.

en tout: il n'y a pas de réponse générale à votre question. Si vous avez du code Python qui est critique pour les performances, essayez d'utiliser autant de fonctionnalités que possible (ou posez une question "Comment faire pour que mon code Python soit plus rapide"). Si cela n'aide pas, essayez d'identifier le code et de le porter à C (ou Cython) et l'utilisation de l'extension.

46
répondu Torsten Marek 2015-01-07 11:07:07

py2c ( http://code.google.com/p/py2c ) peut convertir le code python en c / c++ Je suis le développeur solo de py2c.

16
répondu Ramchandra Apte 2012-07-10 14:00:44

PyPy est un projet de ré-implémentation de Python en Python, utilisant la compilation en code natif comme l'une des stratégies d'implémentation (les autres étant une VM avec JIT, utilisant JVM, etc.). Leurs versions c compilées tournent plus lentement que CPython en moyenne mais beaucoup plus vite pour certains programmes.

Shedskin est un compilateur expérimental Python-to-C++.

Pyrex est une langue spécialement conçue: conçu pour écrire des modules D'extension Python. Il est conçu pour combler le fossé entre le monde agréable, de haut niveau, facile à utiliser de Python et le désordre, monde de bas niveau de C.

13
répondu pdc 2018-03-05 08:07:49

Nuitka est un compilateur Python vers C++ qui se lie à libpython. Il semble être un relativement nouveau projet. L'auteur revendique un amélioration de la vitesse sur CPython sur le référentiel pystone.

12
répondu bcattle 2014-04-09 03:52:37

Pyrex est un sous-ensemble du langage Python qui compile en C, fait par le gars qui a construit le premier liste compréhensions pour Python. Il a été principalement développé pour la construction d'enveloppes, mais peut être utilisé dans un contexte plus général. Cython est une fourche de pyrex maintenue plus activement.

10
répondu ConcernedOfTunbridgeWells 2012-10-14 09:24:16

cela peut sembler raisonnable à première vue, mais il y a beaucoup de choses ordinaires en Python qui ne sont pas directement applicables à une représentation en C sans avoir beaucoup de support D'exécution Python. Par exemple, la dactylographie de canard vient à l'esprit. De nombreuses fonctions en Python qui lisent input peuvent prendre un fichier ou un objet similaire à un fichier , à condition qu'il supporte certaines opérations, par exemple: read () ou readline (). Si vous pensez à ce qu'il faudrait pour cartographier ce type de soutien à C, vous commencez à imaginer exactement le genre de choses que l'exécution Python système déjà fait.

il y a des utilitaires tels que py2exe qui vont regrouper un programme Python et l'exécution en un seul exécutable (dans la mesure du possible).

9
répondu Greg Hewgill 2008-09-26 09:56:08

quelques références supplémentaires:

5
répondu serge-sans-paille 2017-10-27 10:37:32

Jython dispose d'un compilateur ciblant JVM bytecode. Le bytecode est entièrement dynamique, tout comme le langage Python lui-même! Très cool. (Oui, comme L'indique la réponse de Greg Hewgill, le bytecode utilise le Jython runtime, et donc le fichier Jython jar doit être distribué avec votre application.)

3
répondu Chris Jester-Young 2008-09-26 10:00:16

Psyco est une sorte de compilateur JIT (just-in-time): un compilateur dynamique pour Python, exécute le code 2-100 fois plus rapidement, mais il a besoin de beaucoup de mémoire.

en bref: il exécute votre logiciel Python existant beaucoup plus rapidement, sans changement de source mais il ne compile pas pour objecter du code de la même manière qu'un compilateur C.

2
répondu Pierre-Jean Coudert 2008-09-26 09:59:12

, La réponse est "Oui, c'est possible". Vous pouvez prendre du code Python et essayer de le compiler dans le code C équivalent en utilisant L'API CPython. En fait, il y avait un projet Python2C qui faisait exactement cela, mais je n'en avais pas entendu parler depuis de nombreuses années (dans le Python 1.5 days c'est quand je l'ai vu pour la dernière fois.)

vous pouvez essayer de traduire le code Python en C natif autant que possible, et revenir à L'API CPython lorsque vous avez besoin de fonctionnalités Python réelles. J'ai moi-même joué avec cette idée ces derniers mois. C'est, cependant, beaucoup de travail, et une énorme quantité de fonctionnalités Python sont très difficiles à traduire en C: fonctions imbriquées, générateurs, n'importe quoi sauf des classes simples avec des méthodes simples, n'importe quoi impliquant la modification de modules globals à partir de l'extérieur du module, etc, etc.

2
répondu Thomas Wouters 2008-09-26 10:14:09

cela ne compile pas Python en code machine. Mais permet de créer une bibliothèque partagée pour appeler du code Python.

si ce que vous recherchez est un moyen facile d'exécuter du code Python à partir de C sans compter sur des exécutables. Vous pouvez générer une bibliothèque partagée à partir du code python enveloppé de quelques appels à API d'intégration de Python . L'application est une bibliothèque partagée, une .de sorte que vous pouvez utiliser dans de nombreuses autres bibliothèques/applications.

Voici un exemple simple qui créer une bibliothèque partagée, que vous pouvez lien avec un programme C. La bibliothèque partagée exécute le code Python.

le fichier python qui sera exécuté est 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

vous pouvez l'essayer avec python2 -c "import pythoncalledfromc; pythoncalledfromc.main('HELLO') . Il affichera:

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

la bibliothèque partagée sera définie comme suit par callpython.h :

#ifndef CALL_PYTHON
#define CALL_PYTHON

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

#endif

le associé callpython.c est:

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

, Vous pouvez le compiler avec la commande suivante:

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

créer un fichier nommé callpythonfromc.c qui contient ce qui suit:

#include "callpython.h"

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

compiler et exécuter:

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

C'est un exemple très simple. Cela peut fonctionner, mais selon la bibliothèque, il peut être difficile de sérialiser les structures de données C en Python et de Python à C. Les choses peuvent être quelque peu automatisées...

Nuitka pourrait être utile.

il y a aussi numba mais les deux ne visent pas à faire ce que vous voulez exactement. Générer un en-tête C à partir du code Python est possible, mais seulement si vous spécifiez la façon de convertir les types Python en types C ou si vous pouvez inférer cette information. Voir Python astroid pour un analyseur Python ast.

2
répondu amirouche 2017-05-23 11:46:55