Выполнение строк в словарях Python

vypolnenie strok v slovaryah python Интеграция Python/C

Когда выше мы использовали функцию PyRun_String для выполнения выражений и получения результатов, программный код выполнялся в пространстве имен существующего модуля Python. Однако иногда для выполнения строк программного кода удобнее создавать совершенно новое пространство имен, независимое от существующих файлов модулей. Программа на языке C, представленная в примере 20.28, демонстрирует, как это делается. Пространство имен создается как новый объект словаря Python, при этом в процессе участвует ряд новых для нас функций API:

PyDict_New

Создает новый пустой объект словаря.

PyDict_SetItemString

Выполняет присваивание по ключу словаря.

PyDict_GetItemString

Загружает значение из словаря по ключу.

PyRun_String

Выполняет строку программного кода в пространствах имен, как и ранее.

PyEval_GetBuiltins

Получает модуль с областью видимости встроенных элементов.

Главная хитрость здесь заключается в новом словаре. Входные и выходные данные для строк встроенного программного кода отображаются в этот словарь при его передаче в качестве словарей пространств имен кода в вызове функции PyRun_String. В итоге программа на C из примера 20.28 работает в точности, как следующий программный код Python:

>>> d = {}

>>> d[‘Y’] = 2

>>> exec(‘X = 99′, d, d)

>>> exec(‘X = X + Y’, d, d)

>>> print(d[‘X‘])

101

Но здесь каждая операция Python заменяется вызовом C API.

Пример 20.28. PP4E\Integrate\Embed\Basics\embed-dict.c

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

#include <Python.h>

main() { int cval; PyObject *pdict, *pval; printf("embed-dict\n"); Py_Initialize();

/* создать новое пространство имен */

pdict = PyDict_New();

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

PyDict_SetItemString(pdict, "Y", PyLong_FromLong(2)); /* dict[‘Y’] = 2 */ PyRun_String("X = 99", Py_file_input, pdict, pdict); /* вып. инструкц. */ PyRun_String("X = X+Y", Py_file_input, pdict, pdict); /* то же X и Y */ pval = PyDict_GetItemString(pdict, "X"); /* получить dict[‘X’] */

PyArg_Parse(pval, "i", &cval); /* преобразовать в C */

printf("%d\n", cval); /* результат = 101 */

Py_DECREF(pdict);

Py_Finalize();

}

После компиляции и выполнения эта программа на C выведет следующее:

/PP4E/Integrate/Embed/Basics$ ./embed-dict embed-dict

101

На этот раз вывод получился иным: он отражает значение переменной Python X, присвоенное встроенными строками программного кода Python и полученное в C. В целом C может получать атрибуты модуля, либо вызывая функцию PyObject_GetAttrString с объектом модуля, либо обращаясь к словарю атрибутов модуля с помощью PyDict_GetItemString (также можно использовать строки выражений, но не напрямую). В данном случае модуля нет вообще, поэтому для обращения к пространству имен программного кода из C используется доступ к словарю по индексу.

Помимо возможности расчленения пространств имен строк с программным кодом, не зависимых от файлов модулей Python базовой системы, эта схема предоставляет естественный механизм связи. Значения, сохраняемые в новом словаре перед выполнением программного кода, служат входными данными, а имена, которым производится присвоение встроенным программным кодом, впоследствии могут извлекаться из словаря как выходные данные. Например, переменная Y во второй строке ссылается на имя, которому в C присваивается значение 2; значение переменной X присваивается программным кодом Python и извлекается позднее в программе C, как результат вывода.

Здесь есть один тонкий прием, требующий пояснения: словари, используемые в качестве пространств имен выполняемого программного кода, обычно должны содержать ссылку __builtins__ на пространство имен области видимости встроенных объектов, которая устанавливается программным кодом следующего вида:

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

Это неочевидное требование и обычно для модулей и встроенных компонентов, таких как функция exec, оно обрабатывается самим интерпретатором Python. Однако в случае использования собственных словарей пространств имен мы должны определять эту ссылку вручную, если выполняемый программный код должен иметь возможность ссылаться на встроенные имена. Это требование сохраняется в Python 3.X.

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

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

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