するすることを可能にPythonコンパイル機械のコードについて教えてください。
-
02-07-2019 - |
質問
どう実現可能となるPythonコンパイルしれによる中間体Cの表現)機械コードについて教えてください。
ここからう必要があると思われるリンクPythonライブラリは、任意のPython標準ライブラリがPython自体が必要となる場合があるとめ(リンク)です。
また、必要にバンドルのPythonインタプリタがやってみたかった動的評価の表現もサブセットのPythonなることにも役立ちます。
で提供する速度やメモリ使用量の利点?ここからスタートアップ時間のPythonインタプリタが排除することは共有ライブラリも必要な時に起動).
解決
ShedSkin Python-to-C ++コンパイラを試しますが、完璧とはほど遠いです。また、高速化のみが必要な場合は、Psyco-Python JITもあります。しかし、私見これは努力する価値はありません。コードの速度が重要な部分についての最善の解決策は、それらをC / C ++拡張として記述することです。
他のヒント
@Greg Hewgillが言うように、これが常に可能であるわけではないという十分な理由があります。ただし、特定の種類のコード(非常にアルゴリズム的なコードなど)は、「本物」に変換できます。マシンコード。
いくつかのオプションがあります:
- マシンコードを動的に出力する Psyco を使用します。ただし、変換するメソッド/関数を慎重に選択する必要があります。
- PythonにコンパイルされるPython- like 言語である Cython を使用しますC拡張機能
- RPythonの翻訳者がいる PyPy を使用します(Pythonの制限付きサブセット Pythonの最も「動的な」機能の一部をCまたはLLVMにサポートしていません。
- PyPyはまだ非常に実験的です
- すべての拡張機能が存在するわけではありません
その後、既存のパッケージ(freeze、Py2exe、PyInstaller)のいずれかを使用して、すべてを1つのバイナリに入れることができます。
全体として、あなたの質問に対する一般的な答えはありません。パフォーマンスが重要なPythonコードがある場合は、できるだけ多くの組み込み機能を使用してみてください(または「Pythonコードを高速化するにはどうすればよいですか」という質問をしてください)。それでも解決しない場合は、コードを特定してC(またはCython)に移植し、拡張機能を使用してみてください。
py2c( http://code.google.com/p/py2c )は、Pythonコードをc /に変換できます。 C ++ 私はpy2cのソロ開発者です。
これは一見合理的に思えるかもしれませんが、Pythonには多くのPythonランタイムサポートを引き継がずにC表現に直接マッピングできない普通のことがたくさんあります。たとえば、アヒルのタイピングが思い浮かびます。入力を読み取るPythonの多くの関数は、特定の操作をサポートしている限り、ファイルまたはファイルのようなオブジェクトを取ることができます。 read()またはreadline()。このタイプのサポートをCにマッピングするのに何が必要かを考えると、Pythonランタイムシステムが既に行っている種類のことを正確に想像し始めます。
Pythonプログラムとランタイムを単一の実行可能ファイルにバンドルする py2exe などのユーティリティがあります(これまでのところ可能な限り)。
その他の参照:
-
https://github.com/dropbox/pyston は、 Dropboxが開発したPython
-
http://pythran.readthedocs.io/ は、コンパイル時のPythonです。科学計算用のC ++トランスレーター
-
https://github.com/cosmo-ethz/hope は科学計算用のJIT pythonからC ++へのトランスレーター
Jythonには、JVMバイトコードをターゲットとするコンパイラがあります。バイトコードは、Python言語自体と同じように完全に動的です!とてもかっこいい。 (はい、Greg Hewgillの答えが示すように、バイトコードはJythonランタイムを使用するため、Jython jarファイルはアプリと共に配布する必要があります。)
Psyco は、ジャストインタイム(JIT)コンパイラの一種です。Python用の動的コンパイラ、コードを2〜100倍高速に実行しますが、多くのメモリが必要です。
要するに、ソースを変更せずに既存のPythonソフトウェアをはるかに高速に実行しますが、Cコンパイラと同じようにオブジェクトコードにコンパイルしません。
その答えが"はい".などに連れて行くことができPythonコードのみをコンパイルでのCコードを使用CPython APIに含まれています。実際、あPython2Cプロジェクトがかったことも聞いたことがない"と明言を避けで多くの年のPython1.5日はきっとても感じが良かったです。
できる翻訳は、PythonコードをネイティブCでは、秋のCPython API要な時に必要な実際のPythonです。ってtoyingることが自分の前月ます。しかし、ひどく、膨大なPythonの特徴は非常に硬くすC:入れ子の機能、発電機、なんでもが簡単に授業に簡単な方法も含修正モジュールのグローバル変数を外部からのモジュールなどがあります。
これは、Pythonをマシンコードにコンパイルしません。ただし、共有ライブラリを作成してPythonコードを呼び出すことはできます。
探しているのが、execpに頼らずにCからPythonコードを実行する簡単な方法である場合。 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に、PythonからCにシリアル化することはまだ難しいかもしれません。物事はいくらか自動化できます...
Nuitka は参考になりました。
numba もありますが、どちらも正確にやりたいとは考えていません。 PythonコードからCヘッダーを生成することは可能ですが、PythonタイプをCタイプに変換する方法を指定するか、その情報を推測できる場合のみです。 Python astアナライザーについては、 python astroid をご覧ください。