Python(おそらく中間C表現を介して)をマシンコードにコンパイルすることはどの程度実現可能でしょうか?
おそらく、Pythonランタイムライブラリと、Python標準ライブラリであるPythonそれ自体もコンパイル(およびリンク)する必要があります。
また、式の動的評価を行いたい場合はPythonインタープリターをバンドルする必要がありますが、これを許可しなかったPythonのサブセットそれでも有用です。
速度やメモリ使用量の利点はありますか?おそらくPythonインタープリターの起動時間はなくなります(ただし、共有ライブラリーは起動時にロードする必要があります)。
ShedSkin Python-to-C++コンパイラを試してみてください。しかし、完璧とはほど遠いです。また、Psycoがあります-Python高速化のみが必要な場合はJITです。しかし、私見ではこれは努力する価値はありません。 。
@Greg Hewgillが言うように、これが常に可能とは限らないのには十分な理由があります。ただし、特定の種類のコード(非常にアルゴリズム的なコードなど)は、「実際の」マシンコードに変換できます。
いくつかのオプションがあります。
その後、既存のパッケージ(freeze、Py2exe、PyInstaller)のいずれかを使用して、すべてを1つのバイナリに入れることができます。
全体として、あなたの質問に対する一般的な答えはありません。 Pythonパフォーマンスが重要なコードがある場合は、できるだけ多くの組み込み機能を使用してみてください(または、「Pythonそれが解決しない場合は、コードを特定してC(またはCython)に移植し、拡張機能を使用してみてください。
py2c( http://code.google.com/p/py2c )は、pythonコードをc/c ++に変換できます。私はpy2cのソロ開発者です。
Pyrex は、CにコンパイルされるPython言語のサブセットであり、Pythonの最初のビルド list comprehensions で行われました。主にラッパーを構築するために開発されましたが、より一般的なコンテキストで使用することができます Cython は、パイレックスのより積極的に維持されるフォークです。
これは一見合理的と思われるかもしれませんが、Pythonには多くのPythonランタイムのサポート。たとえば、ダックタイピングが思い浮かびます。Python読み取り入力はファイルまたはファイルのようなものをとることができます) オブジェクト、特定の操作(read()やreadline()など)をサポートしている限り、このタイプのサポートをCにマッピングするのに何が必要かを考えると、想像し始めますPythonランタイムシステムが既に行っていることの種類。
py2exe などのユーティリティがあり、Pythonプログラムとランタイムを単一の実行可能ファイルに(可能な限り)バンドルします。
いくつかの追加の参照:
https://github.com/dropbox/pyston はPython Dropboxによって開発されたためのJITコンパイラです
http://pythran.readthedocs.io/ はコンパイル時python科学計算用C++トランスレーターへ
https://github.com/cosmo-ethz/hope はJIT python科学計算用C++トランスレーターへ
Jythonには、JVMバイトコードをターゲットとするコンパイラがあります。バイトコードは、Python言語そのものです!非常にクールです。アプリとともに配布されます。)
Python→11l→C++ transpiler を試してください。
Psyco は一種のジャストインタイム(JIT)コンパイラーです。Python用の動的コンパイラーで、コードを2〜100倍高速に実行しますが、多くのメモリが必要です。
要するに、ソースを変更せずに既存のPythonソフトウェアをはるかに高速で実行しますが、Cコンパイラと同じようにオブジェクトコードにコンパイルしません。
答えは「はい、可能です」です。 Pythonコードを取得し、CPython APIを使用して同等のCコードにコンパイルしようとすることができます。実際には、それを行うPython2Cプロジェクトがありましたが、聞いたことがありませんそれについては長年(Python 1.5日は私が最後に見たときに戻っています。)
PythonコードをできるだけネイティブCに変換し、実際のPython機能が必要な場合はCPython APIにフォールバックできます。私は先月または2か月間、そのアイデアをいじっていましたが、それは非常に多くの作業であり、膨大な量のPython機能をC:入れ子関数に変換するのは非常に困難です、ジェネレータ、シンプルなメソッドを備えたシンプルなクラス以外、モジュールの外部からモジュールグローバルを変更することなどが含まれます。
これは、マシンコードにPythonをコンパイルしません。ただし、Pythonコードを呼び出すための共有ライブラリを作成できます。
探しているのが、execpに依存せずにCからPythonコードを実行する簡単な方法である場合。python code wrapped Python埋め込みAPI を数回呼び出すだけです。アプリケーションは共有ライブラリであり、他の多くのライブラリ/アプリケーションで使用できる.soです。
Cプログラムとリンクできる共有ライブラリを作成する簡単な例を次に示します。共有ライブラリはPythonコードを実行します。
実行されるpythonファイルは_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
_
python2 -c "import pythoncalledfromc; pythoncalledfromc.main('HELLO')
で試すことができます。出力されます:
_python is called from c
string sent by «c» code is:
HELLO
end of «c» code input
_
共有ライブラリは、_callpython.h
_によって次のように定義されます。
_#ifndef CALL_PYTHON
#define CALL_PYTHON
void callpython_init(void);
int callpython(char ** arguments);
void callpython_finalize(void);
#endif
_
関連する_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();
}
_
次のコマンドでコンパイルできます:
_gcc `python2.7-config --ldflags` `python2.7-config --cflags` callpython.c -lpython2.7 -shared -fPIC -o callpython.so
_
次を含む_callpythonfromc.c
_という名前のファイルを作成します。
_#include "callpython.h"
int main(void) {
char * example = "HELLO";
callpython_init();
callpython(&example);
callpython_finalize();
return 0;
}
_
コンパイルして実行します:
_gcc callpythonfromc.c callpython.so -o callpythonfromc
PYTHONPATH=`pwd` LD_LIBRARY_PATH=`pwd` ./callpythonfromc
_
これは非常に基本的な例です。動作しますが、ライブラリによっては、Cデータ構造をPythonおよびfrom Python to Cにシリアル化することは依然として困難です。 ...
Nuitka が役立つ場合があります。
また、 numba がありますが、どちらもあなたが望むことを正確に行うことを目指していません。 PythonコードからCヘッダーを生成できますが、PythonタイプをCタイプに変換する方法を指定するか、その情報を推測できます。 python astroid Python astアナライザーの場合。