Предварительная компиляция строк в байт-код Python

predvaritelnaya kompilyaciya strok v bajt kod python Интеграция Python/C

Наконец, при вызове объектов функций Python из C вы фактически выполняете откомпилированный байт-код, связанный с объектом (например, телом функции), который обычно создается на этапе импортирования вмещающего модуля. При выполнении строк Python должен предварительно скомпилировать строку. Так как компиляция является медленным процессом, это может повлечь существенные потери времени, если предполагается многократное выполнение строки. Чтобы избежать их, откомпилируйте строку в объект байт-кода, который будет выполняться позднее, с помощью функций API, представленных в примере 20.29.

Py_CompileString

Компилирует строку программного кода, возвращает объект байткода.

PyEval_EvalCode

Выполняет объект скомпилированного байт-кода.

Первая из этих функций принимает флаг режима, обычно передаваемый функции PyRun_String, и второй строковый аргумент, используемый только в сообщениях об ошибках. Вторая функция принимает два словаря пространств имен. Эти две функции API использованы в примере 20.29 для компиляции и выполнения трех строк программного кода Python.

Пример 20.29. PP4E\Integrate\Embed\Basics\embed-bytecode.c

/* предварительная компиляция строк программного кода в объекты байт-кода */

#include <Python.h>

#include <compile.h>

#include <eval.h>

main() { int i; char *cval; PyObject *pcode1, *pcode2, *pcode3, *presult, *pdict; char *codestr1, *codestr2, *codestr3;

printf("embed-bytecode\n");

Py_Initialize();

codestr1 = "import usermod\nprint(usermod.message)"; /* инструкции */ codestr2 = "usermod.transform(usermod.message)"; /* выражение */ codestr3 = "print(‘%d:%d’ % (X, X ** 2), end=’ ‘)"; /* входное знач. X */

/* создать новый словарь пространства имен */ pdict = PyDict_New();

if (pdict == NULL) return -1;

PyDict_SetItemString(pdict, "__builtins__", PyEval_GetBuiltins());

/* скомпилировать строки программного кода в объекты байткода */ pcode1 = Py_CompileString(codestr1, "<embed>", Py_file_input); pcode2 = Py_CompileString(codestr2, "<embed>", Py_eval_input); pcode3 = Py_CompileString(codestr3, "<embed>", Py_file_input);

/* выполнить скомпилированный байт-код в пространстве имен словаря */ if (pcode1 && pcode2 && pcode3) {

(void) PyEval_EvalCode((PyCodeObject *)pcode1, pdict, pdict); presult = PyEval_EvalCode((PyCodeObject *)pcode2, pdict, pdict); PyArg_Parse(presult, "s", &cval);

printf("%s\n", cval);

Py_DECREF(presult);

/* выполнить объект байт-кода несколько раз */ for (i = 0; i <= 10; i++) {

PyDict_SetItemString(pdict, "X", PyLong_FromLong(i));

(void) PyEval_EvalCode((PyCodeObject *)pcode3, pdict, pdict);

}

printf("\n");

}

/* освободить использовавшиеся объекты */

Py_XDECREF(pdict);

Py_XDECREF(pcode1);

Py_XDECREF(pcode2);

Py_XDECREF(pcode3);

Py_Finalize();

}

Эта программа объединяет в себе ряд приемов, которые мы уже видели. Например, пространством имен, в котором выполняются скомпилированные строки, является вновь создаваемый словарь (а не существующий объект модуля), а входные данные передаются строкам программного кода в виде предустановленных переменных в пространстве имен. После компиляции и выполнения первая часть вывода программы аналогична предыдущим примерам из этого раздела, но последняя строчка представляет 11-кратное выполнение одной и той же предварительно откомпилированной строки:

/PP4E/Integrate/Embed/Basics$ embed-bytecode embed-bytecode

The meaning of life

THE MEANING OF PYTHON

0:0 1:1 2:4 3:9 4:16 5:25 6:36 7:49 8:64 9:81 10:100

Если ваша система выполняет строки программного кода Python несколько раз, предварительное компилирование их в байт-код позволит получить значительное ускорение. Этот этап не является обязательным в других контекстах, где производится обращение к вызываемым объектам Python, включая типичный случай использования технологии встраивания, представленный в следующем разделе.

Использованная литература:

Марк Лутц — Программирование на Python, 4-е издание, II том, 2011

Каталог сайтов Всего.ру
Оцените статью
Секреты программирования
Добавить комментарий