Python'u makine koduna derlemek mümkün müdür?


128

Python'u (muhtemelen bir ara C temsili aracılığıyla) makine koduna derlemek ne kadar mümkün olabilir?

Muhtemelen bir Python çalışma zamanı kitaplığına bağlanması gerekecek ve Python standart kitaplığının Python olan herhangi bir parçasının da derlenmesi (ve bağlanması) gerekecektir.

Ayrıca, ifadelerin dinamik değerlendirmesini yapmak istiyorsanız Python yorumlayıcısını paketlemeniz gerekir, ancak belki de buna izin vermeyen bir Python alt kümesi yine de yararlı olacaktır.

Herhangi bir hız ve / veya bellek kullanım avantajı sağlar mı? Muhtemelen Python yorumlayıcısının başlangıç ​​zamanı ortadan kalkacaktır (ancak paylaşılan kitaplıkların yine de başlangıçta yüklenmesi gerekir).


2
Btw, nesne kodu yerine "makine kodu" sorduysanız sorunuz IMHO daha net olacaktır.
Torsten Marek

Yanıtlar:


31

ShedSkin Python-to-C ++ derleyicisini deneyin , ancak mükemmel olmaktan uzaktır. Ayrıca, yalnızca hızlandırma gerekliyse Psyco - Python JIT vardır. Ancak IMHO bu çabaya değmez. Kodun hız açısından kritik bölümleri için en iyi çözüm, bunları C / C ++ uzantıları olarak yazmaktır.


5
Bilginize, ShedSkin Windows desteğini düşürdü.
sorin

2
@sorin: pekala, bugün pencereleri destekliyor ... code.google.com/p/shedskin/downloads/…

2
Hızla en iyi çözüm hala PyPy olabilir .
Cees Timmerman

shedskin yaklaşık iki yıldır bu konuda hiçbir çalışma yapmadı. :(
Perkins

53

@Greg Hewgill'in söylediği gibi, bunun her zaman mümkün olmamasının iyi nedenleri var. Bununla birlikte, belirli kod türleri (çok algoritmik kod gibi) "gerçek" makine koduna dönüştürülebilir.

Birkaç seçenek var:

  • Psyco kullanınMakine kodunu dinamik olarak . Yine de hangi yöntemleri / işlevleri dönüştüreceğinizi dikkatlice seçmelisiniz.
  • Python C uzantısında derlenmiş Python benzeri bir dil olan Cython'u kullanın
  • Kullanım PyPy RPython gelen bir çevirmen (a sahiptir, kısıtlı alt kümesi C veya LLVM için en "dinamik" Python bazı özelliklerini desteklemez Python).
    • PyPy hala oldukça deneysel
    • tüm uzantılar mevcut olmayacak

Bundan sonra, her şeyi tek bir ikiliye koymak için mevcut paketlerden birini (donma, Py2exe, PyInstaller) kullanabilirsiniz.

Sonuç olarak: Sorunuzun genel bir cevabı yok. Performans açısından kritik Python kodunuz varsa, olabildiğince çok yerleşik işlevsellik kullanmaya çalışın (veya "Python kodumu nasıl daha hızlı yapabilirim" sorusunu sorun). Bu işe yaramazsa, kodu belirleyip C'ye (veya Cython'a) aktarmaya çalışın ve uzantıyı kullanın.


3
Pypy, Psyco'nun halefi
bcattle

19

py2c ( https://github.com/pradyun/Py2C ) python kodunu c / c ++ 'ya dönüştürebilir. Ben py2c'nin tek geliştiricisiyim.


Bu kullanışlı bir araç gibi görünüyor. Hâlâ bakılıyor mu?
Anderson Yeşil

@AndersonGreen En son üzerinde çalıştığımda erken bir geliştirme aşamasında (muhtemelen şimdi benzer). Projeden ayrıldım çünkü ben tembelim ben b̶u̶s̶y̶. "Önemli" metnini fark etmediyseniz, şimdi GitHub'a taşınmıştır.
Ramchandra Apte

Bağlantı , farklı bir proje gibi görünen yenilgisiz yükleyiciye işaret ediyor . Py2c hala GitHub'da mevcut mu?
Anderson Green

@AndersonGreen Wow bu kadar uzun süredir fark edilmedi! İşte gidiyorsun.
Ramchandra Apte

Bağlantısını code.google.com/p/py2c artık güncellenmesi gerekiyor bu yüzden hala unvanquished-yükleyici işaret ediyor.
Anderson Green

15

PyPy , Python'u Python'da yeniden uygulama, uygulama stratejilerinden biri olarak yerel koda derlemeyi kullanan bir projedir (diğerleri JIT ile bir VM, JVM kullanarak vb.). Derlenmiş C sürümleri ortalama olarak CPython'dan daha yavaş, ancak bazı programlar için çok daha hızlı çalışır.

Shedskin deneysel bir Python-to-C ++ derleyicisidir.

Pyrex , Python eklenti modülleri yazmak için özel olarak tasarlanmış bir dildir. Güzel, yüksek seviyeli, kullanımı kolay Python dünyası ile C'nin dağınık, düşük seviyeli dünyası arasındaki boşluğu kapatmak için tasarlanmıştır.


3
Cython, Pyrex'in daha yaygın olarak kullanılan, daha aktif olarak geliştirilmiş dostça çatalı.
Mike Graham

"Python'un güzel, yüksek seviyeli, kullanımı kolay dünyası ve C'nin dağınık, düşük seviyeli dünyası" - komik Ben sadece C ve assembler'ın ne kadar "güzel" ve basit olduğunu ve Python'un içinde yaşadığını düşünüyordum " dağınık "," üst düzey "dünya
Ters Mühendis


10

Bu ilk bakışta makul görünebilir, ancak Python'da çok fazla Python çalışma zamanı desteği taşımadan bir C temsiliyle doğrudan eşleştirilemeyen birçok sıradan şey vardır. Örneğin ördek yazma akla geliyor. Python'da girdi okuyan birçok işlev , belirli işlemleri desteklediği sürece bir dosya veya dosya benzeri bir nesne alabilir , örn. read () veya readline (). Bu tür bir desteği C ile eşlemek için ne gerektiğini düşünürseniz, Python çalışma zamanı sisteminin halihazırda yaptığı şeyleri tam olarak hayal etmeye başlarsınız.

Py2exe gibi bir Python programını ve çalışma zamanını tek bir yürütülebilir dosyada (mümkün olduğunca) paketleyecek yardımcı programlar vardır .


1
Ya amacım, statik olarak derlenen dillerin (en azından benim görüşüme göre) çalışma zamanında patlaması daha az olası olduğu için kodun derlendiğinden emin olmak olsaydı? Bazı belirlemek mümkün mü foo.xçünkü ifade çalışmaz fooolmaz xdenir anda. Python için herhangi bir statik kod denetleyicisi var mı? Python bir .Net derlemesinde derlenebilir ...
Hamish Grubijan 20'12

10

Pyrex , Python için ilk liste anlayışlarını oluşturan kişi tarafından C'ye derlenen Python dilinin bir alt kümesidir . Esas olarak sarmalayıcılar oluşturmak için geliştirilmiştir ancak daha genel bir bağlamda kullanılabilir. Cython , daha aktif bir şekilde korunan bir pyrex çatalıdır .


2
Cython, Pyrex'in daha yaygın olarak kullanılan, daha aktif olarak geliştirilmiş dostça çatalı.
Mike Graham


3

Jython, JVM bayt kodunu hedefleyen bir derleyiciye sahiptir. Bayt kodu tıpkı Python dilinin kendisi gibi tamamen dinamiktir! Çok havalı. (Evet, Greg Hewgill'in cevabının ima ettiği gibi, bayt kodu Jython çalışma zamanını kullanır ve bu nedenle Jython jar dosyası uygulamanızla birlikte dağıtılmalıdır.)


2

psyco bir tür tam zamanında (JIT) derleyicidir: Python için dinamik derleyici, kodu 2-100 kat daha hızlı çalıştırır, ancak çok fazla belleğe ihtiyaç duyar.

Kısacası: mevcut Python yazılımınızı kaynağınızda değişiklik olmadan çok daha hızlı çalıştırır, ancak bir C derleyicisinin yapacağı gibi nesne koduna derleme yapmaz.


2

Cevap "Evet, mümkün". Python kodunu alıp CPython API kullanarak eşdeğer C kodunda derlemeyi deneyebilirsiniz. Aslında, tam da bunu yapan bir Python2C projesi vardı, ancak bunu yıllardır duymadım (Python'da 1.5 gün onu en son gördüğüm gündü.)

Python kodunu mümkün olduğunca yerel C'ye çevirmeyi deneyebilir ve gerçek Python özelliklerine ihtiyacınız olduğunda CPython API'ye geri dönebilirsiniz. Ben de son bir iki aydır bu fikirle oynuyordum. Bununla birlikte, çok fazla iş ve muazzam miktarda Python özelliğinin C'ye çevrilmesi çok zordur: yuvalanmış işlevler, jeneratörler, basit yöntemlerle basit sınıflar, modülün dışından modül globallerini değiştirmeyi içeren herhangi bir şey, vb. , vb.


2

Bu, Python'u makine koduna derlemez. Ancak Python kodunu çağırmak için paylaşılan bir kitaplık oluşturmaya izin verir.

Eğer aradığınız şey Python kodunu C'den çalıştırmanın kolay bir yoluysa, execp maddelerine güvenmeden. Python gömme API'sine yapılan birkaç çağrı ile sarmalanmış python kodundan paylaşılan bir kitaplık oluşturabilirsiniz . Uygulama, diğer birçok kitaplıkta / uygulamada kullanabileceğiniz bir paylaşılan kitaplıktır.

Burada, bir C programına bağlayabileceğiniz, paylaşılan bir kitaplık oluşturan basit bir örnek var. Paylaşılan kitaplık Python kodunu yürütür.

Çalıştırılacak python dosyası 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

İle deneyebilirsiniz python2 -c "import pythoncalledfromc; pythoncalledfromc.main('HELLO'). Çıktı:

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

Paylaşılan kitaplık aşağıdakiler tarafından tanımlanacaktır callpython.h:

#ifndef CALL_PYTHON
#define CALL_PYTHON

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

#endif

İlişkili callpython.c:

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

Aşağıdaki komutla derleyebilirsiniz:

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

callpythonfromc.cAşağıdakileri içeren bir dosya oluşturun :

#include "callpython.h"

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

Derleyin ve çalıştırın:

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

Bu çok basit bir örnek. Çalışabilir, ancak kitaplığa bağlı olarak C veri yapılarını Python'a ve Python'dan C'ye serileştirmek yine de zor olabilir. İşler bir şekilde otomatikleştirilebilir ...

Nuitka yardımcı olabilir.

Ayrıca numba var ama ikisi de tam olarak istediğiniz şeyi yapmayı hedeflemiyor. Python kodundan bir C başlığı oluşturmak mümkündür, ancak yalnızca Python türlerinin C türlerine nasıl dönüştürüleceğini belirtirseniz veya bu bilgileri çıkarabilirseniz. Bir Python ast analizörü için python astroid'e bakın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.