Главная страница

справочник по Python. мм isbn 9785932861578 9 785932 861578


Скачать 4.21 Mb.
Названиемм isbn 9785932861578 9 785932 861578
Анкорсправочник по Python
Дата08.05.2022
Размер4.21 Mb.
Формат файлаpdf
Имя файлаBizli_Python-Podrobnyy-spravochnik.440222.pdf
ТипСправочник
#518195
страница68 из 82
1   ...   64   65   66   67   68   69   70   71   ...   82
Потоки управления
Глобальная блокировка интерпретатора не позволяет интерпретатору вы- полнять более одного потока управления одновременно. Если функция, реализованная в модуле расширения, выполняется достаточно продолжи- тельное время, она может заблокировать выполнение остальных потоков управления. Это обусловлено тем, что перед каждым вызовом функции в расширении приобретается блокировка. Если модуль расширения допу- скает возможность работы в многопоточном режиме, в нем можно восполь- зоваться следующими макроопределениями, позволяющими освобождать и повторно приобретать глобальную блокировку интерпретатора:
Py_BEGIN_ALLOW_THREADS
Освобождает глобальную блокировку интерпретатора и позволяет интер- претатору выполнять другие потоки управления одновременно с расшире- нием. Расширение на языке C не должно вызывать функции Python C API после освобождения блокировки.

754
Глава 26. Расширение и встраивание интерпретатора Python
Py_END_ALLOW_THREADS
Повторно приобретает глобальную блокировку интерпретатора. Расшире- ние будет приостановлено, пока блокировка не будет приобретена.
Следующий пример иллюстрирует использование этих макроопределений:
PyObject *py_wrapper(PyObject *self, PyObject *args) {
...
PyArg_ParseTuple(args, ...)
Py_BEGIN_ALLOW_THREADS
result = run_long_calculation(args);
Py_END_ALLOW_THREADS
...
return Py_BuildValue(fmt,result);
}
Встраивание интерпретатора Python
Интерпретатор Python также может встраиваться в приложения на язы-
Python также может встраиваться в приложения на язы- также может встраиваться в приложения на язы- ке C. При встраивании интерпретатор Python действует, как библиотека, с помощью которой программы на языке C могут инициализировать ин-
C могут инициализировать ин- могут инициализировать ин- терпретатор, запускать с его помощью сценарии и фрагменты программно- го кода, загружать библиотечные модули, а также манипулировать функ- циями и объектами, реализованными на языке Python.
Порядок встраивания
При встраивании за запуск интерпретатора отвечает программа на язы- ке C. Ниже приводится пример простой программы на языке C, которая иллюстрирует минимально возможный программный код, реализующий встраивание:
#include int main(int argc, char **argv) {
Py_Initialize();
PyRun_SimpleString(“print(‘Hello World’)”);
Py_Finalize();
return 0;
}
В этом примере программа инициализирует интерпретатор, выполняет ко- роткий сценарий в виде строки и закрывает интерпретатор. Прежде чем углубляться в эту тему далее, обычно бывает полезно рассмотреть действу- ющий пример.
Компиляция и связывание
Чтобы скомпилировать программу на языке C, которая встраивает интер-
C, которая встраивает интер-
, которая встраивает интер- претатор, в системе UNIX, программа должна подключить заголовочный файл “Python.h” и быть скомпонована с библиотекой интерпретатора, такой как libpython2.6.a. Заголовочный файл обычно находится в каталоге /usr/
local/include/python2.6
, а библиотека – в каталоге /usr/local/lib/python2.6/

Встраивание интерпретатора Python
755
config
. В системе Windows эти файлы находятся в каталоге установки Py-
Windows эти файлы находятся в каталоге установки Py- эти файлы находятся в каталоге установки Py-
Py- thon. Имейте в виду, что интерпретатор может зависеть от других библио-
. Имейте в виду, что интерпретатор может зависеть от других библио- тек, которые вам также следует включить в инструкции компоновки. К со- жалению, эта процедура зависит от типа платформы и от того, с какими па- раметрами была выполнена сборка интерпретатора Python, поэтому вам, возможно, придется повозиться.
Запуск и основные операции интерпретатора
Ниже перечислены функции, которые используются для запуска интер- претатора и выполнения сценариев с его помощью:
int PyRun_AnyFile(FILE *fp, char *filename)
Если fp представляет интерактивное устройство, например терминал в UNIX, эта функция вызовет функцию PyRun_InteractiveLoop(). В против-
В против- против- против- ном случае – функцию PyRun_SimpleFile(). В аргументе filename передается строка с именем входного потока. Это имя будет фигурировать в сообще- с именем входного потока. Это имя будет фигурировать в сообще- с именем входного потока. Это имя будет фигурировать в сообще- именем входного потока. Это имя будет фигурировать в сообще- именем входного потока. Это имя будет фигурировать в сообще- входного потока. Это имя будет фигурировать в сообще- входного потока. Это имя будет фигурировать в сообще- потока. Это имя будет фигурировать в сообще- потока. Это имя будет фигурировать в сообще-
. Это имя будет фигурировать в сообще-
Это имя будет фигурировать в сообще- имя будет фигурировать в сообще- имя будет фигурировать в сообще- будет фигурировать в сообще- будет фигурировать в сообще- фигурировать в сообще- фигурировать в сообще- в сообще- в сообще- сообще- сообще- ниях интерпретатора об ошибках. Если в аргументе filename передать NULL, в качестве имени файла по умолчанию будет использоваться строка “???”.
int PyRun_SimpleFile(FILE *fp, char *filename)
Похожа на функцию PyRun_SimpleString(), за исключением того, что про- грамма на языке Python извлекается из файла fp.
int PyRun_SimpleString(char *command)
Выполняет команду command в контексте модуля __main__ интерпретатора.
Возвращает 0 в случае успеха и -1 – в случае появления исключения.
int PyRun_InteractiveOne(FILE *fp, char *filename)
Выполняет единственную интерактивную команду.
int PyRun_InterativeLoop(FILE *fp, char *filename)
Запускает интерпретатор в интерактивном режиме.
void Py_Initialize()
Инициализирует интерпретатор Python. Эта функция должна вызываться перед любыми другими функциями C API интерпретатора, за исключени- любыми другими функциями C API интерпретатора, за исключени- любыми другими функциями C API интерпретатора, за исключени- другими функциями C API интерпретатора, за исключени- другими функциями C API интерпретатора, за исключени- функциями C API интерпретатора, за исключени- функциями C API интерпретатора, за исключени-
C API интерпретатора, за исключени- интерпретатора, за исключени-
, за исключени- за исключени- исключени- исключени- ем функций Py_SetProgramName(), PyEval_InitThreads(), PyEval_ReleaseLock() и PyEval_AcquireLock().
int Py_IsInitialized()
Возвращает 1, если интерпретатор был инициализирован, 0 – в противном случае.
void Py_Finalize()
Завершает работу интерпретатора, уничтожая все вложенные потоки управления и объекты, созданные после вызова Py_Initialize(). Обычно эта функция освобождает всю память, выделенную интерпретатором. Однако циклические ссылки и модули расширений способны вызвать утечки па- мяти, которые не могут быть устранены этой функцией.

756
Глава 26. Расширение и встраивание интерпретатора Python
void Py_SetProgramName(char *name)
Определяет имя программы, которое обычно можно найти в переменной argv[0]
модуля sys. Эта функция должна вызываться только перед вызовом
Py_Initialize()
char *Py_GetPrefix()
Возвращает путь установки платформонезависимых файлов. Это то же са- мое значение, которое можно найти в переменной sys.prefix.
char *Py_GetExecPrefix()
Возвращает путь установки платформозависимых файлов. Это то же самое значение, которое можно найти в переменной sys.exec_prefix.
char *Py_GetProgramFullPath()
Возвращает полный путь к выполняемому файлу интерпретатора Python.
char *Py_GetPath()
Возвращает путь по умолчанию поиска модулей. Возвращаемая строка со- держит имена каталогов, разделенные символом-разделителем, который используется текущей платформой (: – в UNIX, ; – в DOS/Windows).
int PySys_SetArgv(int argc, char **argv)
Определяет параметры командной строки для заполнения значения пере- менной sys.argv. Эта функция должна вызываться до вызова функции Py_
Initialize()
Обращение к интерпретатору Python
из программы на языке C
Несмотря на существование большого количества способов доступа к ин- терпретатору из программ на языке C, тем не менее чаще всего используют-
C, тем не менее чаще всего используют-
, тем не менее чаще всего используют- ся четыре основные операции:
• Импортирование библиотечных модулей Python (имитация инструк-
Python (имитация инструк-
(имитация инструк- ции import).
• Получение ссылок на объекты, определяемые в модулях.
• Вызов функций на языке Python, обращение к классам и методам.
• Обращение к атрибутам объектов (к данным или к методам)
Все эти операции могут выполняться с помощью следующих функций ин- терфейса C API доступа к программному коду Python:
PyObject *PyImport_ImportModule(const char *modname)
Импортирует модуль modname и возвращает ссылку на объект модуля.
PyObject *PyObject_GetAttrString(PyObject *obj, const char *name)
Возвращает значение атрибута объекта. Эквивалентно обращению к атри- буту obj.name в программе на языке Python.

Встраивание интерпретатора Python
757
int PyObject_SetAttrString(PyObject *obj, const char *name, PyObject *value)
У
станавливает значение атрибута объекта. Эквивалентно операции при- сваивания obj.name = value в программе на языке Python.
PyObject *PyEval_CallObject(PyObject *func, PyObject *args)
Вызывает функцию func с аргументами args. func – это вызываемый объект на языке Python (функция, метод, класс и так далее). args – кортеж аргу- ментов.
PyObject *PyEval_CallObjectWithKeywords(PyObject *func, PyObject *args, PyOb-
ject *kwargs)
Вызывает функцию func с позиционными аргументами args и именован- ными аргументами kwargs. func – это вызываемый объект, args – кортеж и kwargs – словарь.
Следующий пример иллюстрирует использование этих функций для об- ращения к различным компонентам модуля re из программы на языке C.
Эта программа выводит все cтроки, прочитанные из потока stdin и соответ- ствующие регулярному выражению, переданному пользователем в виде аргумента.
#include “Python.h”
int main(int argc, char **argv) {
PyObject *re;
PyObject *re_compile;
PyObject *pat;
PyObject *pat_search;
PyObject *args;
char buffer[256];
ёёё
if (argc != 2) {
fprintf(stderr,”Порядок использования: %s шаблон\n”,argv[0]);
exit(1);
}
ёёё
Py_Initialize();
ёёё
/* import re */
re = PyImport_ImportModule(“re”);
ёёё
/* pat = re.compile(pat,flags) */
re_compile = PyObject_GetAttrString(re,”compile”);
args = Py_BuildValue(“(s)”, argv[1]);
pat = PyEval_CallObject(re_compile, args);
Py_DECREF(args);
ёёё
/* pat_search = pat.search – связанный метод */
pat_search = PyObject_GetAttrString(pat,”search”);
ёёё
/* Прочитать строки и выполнить сопоставление */
while (fgets(buffer,255,stdin)) {
PyObject *match;
args = Py_BuildValue(“(s)”, buffer);
ёёё

758
Глава 26. Расширение и встраивание интерпретатора Python
/* match = pat.search(buffer) */
match = PyEval_CallObject(pat_search,args);
Py_DECREF(args);
if (match != Py_None) {
printf(“%s”,buffer);
}
Py_XDECREF(match);
}
Py_DECREF(pat);
Py_DECREF(re_compile);
Py_DECREF(re);
Py_Finalize();
return 0;
}
При встраивании интерпретатора Python чрезвычайно важно обеспечить корректное управление счетчиками ссылок. В частности, необходимо уменьшать счетчики ссылок в любых объектах, созданных в программном коде на языке C или возвращаемых программному коду на языке C в ре-
C или возвращаемых программному коду на языке C в ре- или возвращаемых программному коду на языке C в ре-
C в ре- в ре- зультате вызовов функций.
Преобразование объектов на языке Python
в объекты на языке C
Важной проблемой при использовании встроенного интерпретатора явля- ется преобразование результатов вызова функций или методов на языке
Python в соответствующее представление на языке C. Как правило, при выполнении таких операций необходимо заранее точно знать тип данных, возвращаемых функцией. К сожалению, не существует высокоуровневой вспомогательной функции, такой как PyArg_ParseTuple(), для преобразова- ния единственного объекта. Однако существует несколько низкоуровне- вых функций, которые перечислены ниже, способных преобразовывать некоторые простейшие типы данных Python в соответствующее представ-
Python в соответствующее представ- в соответствующее представ- ление на языке C, при условии, что заранее точно известно, преобразование какого объекта на языке Python выполняется:
Функции преобразования объектов Python в представление на языке C
long PyInt_AsLong(PyObject *)
long PyLong_AsLong(PyObject *)
double PyFloat_AsDouble(PyObject *)
char *PyString_AsString(PyObject *)
(только в Python 2)
char *PyBytes_AsString(PyObject *)
(только в Python 3)
Если вам потребуется работать с более сложными типами данных, обра- щайтесь к описанию C API (http://docs.python.org/c-api).

Модуль ctypes
759
Модуль ctypes
М
одуль ctypes обеспечивает доступ к функциям в библиотеках DLL и в раз-
DLL и в раз- и в раз- деляемых библиотеках, написанных на языке C, из программного кода на языке Python. Хотя вам и потребуется знать определенные детали, относя-
Python. Хотя вам и потребуется знать определенные детали, относя-
. Хотя вам и потребуется знать определенные детали, относя- щиеся к библиотеке (имена, входные аргументы, типы аргументов и воз- вращаемых значений и так далее), вы можете использовать модуль ctypes для доступа к программному коду, написанному на языке C, без необходи-
C, без необходи-
, без необходи- мости создавать функции-обертки и даже без необходимости использовать компилятор C. Модуль ctypes является важным модулем в стандартной библиотеке, обладающим весьма широкими функциональными возмож- ностями. Ниже описываются значимые составляющие этого модуля, зна- комство с которыми необходимо, чтобы начать работать с ним.
Загрузка разделяемых библиотек
Ниже перечислены классы, которые используются для загрузки разделяе- мых библиотек, написанных на языке C, и возвращают экземпляры, пред-
C, и возвращают экземпляры, пред-
, и возвращают экземпляры, пред- ставляющие их содержимое:
CDLL(name [, mode [, handle [, use_errno [, use_last_error]]]])
Класс, представляющий стандартную разделяемую библиотеку языка C.
В аргументе name передается имя библиотеки, такое как ‘libc.so.6’ или ‘ms- vcrt.dll’
. В аргументе mode передается флаг, который определяет, как будет загружаться библиотека и как она будет передаваться функции dlopen() в UNIX. Этот аргумент представляет собой битовую маску, составленную из флагов RTLD_LOCAL, RTLD_GLOBAL и RTLD_DEFAULT (по умолчанию), объединяе- мых битовой операцией ИЛИ. В Windows аргумент mode игнорируется. Ар- игнорируется. Ар-
. Ар-
Ар- гумент handle определяет дескриптор уже загруженной библиотеки (если доступен). По умолчанию он принимает значение None. В аргументе use_er-
_er-
er-
rno
передается логический флаг, добавляющий дополнительный уровень безопасности при работе с переменной errno языка C в загружаемой библио-
C в загружаемой библио- в загружаемой библио- теке. Когда задействован этот уровень, локальная копия переменной errno в текущем потоке управления сохраняется перед вызовом любых внешних функций и восстанавливается после вызова. По умолчанию аргумент use_
errno
принимает значение False. В аргументе use_last_error передается ло- гический флаг, который разрешает использовать пару функций get_last_
error()
и set_last_error() для управления системным кодом ошибки. Чаще всего эти функции используются в Windows. По умолчанию аргумент use_
last_error
принимает значение False.
WinDLL(name [, mode [, handle [, use_errno [, use_last_error]]]])
То же, что и CDLL(), за исключением того, что в данном случае предпола- гается, что все функции в загружаемой библиотеке следуют стандартному соглашению Windows stdcall о вызовах (Windows).
Следующую функцию можно использовать, чтобы искать в системе раз- деляемые библиотеки и сконструировать имя, подходящее для использо- вания в аргументе name предыдущих конструкторов классов. Эта функция определена в модуле ctypes.util:

760
Глава 26. Расширение и встраивание интерпретатора Python
find_library(name)
Определена в модуле ctypes.util. Возвращает полный путь к библиотеке с именем name. В аргументе name передается имя библиотеки без расшире- ния, такое как ‘libc’, ‘libm’ и так далее. Строка, возвращаемая функцией, содержит полный путь к файлу библиотеки, такой как ‘/usr/lib/libc.so.6’.
Поведение этой функции в значительной степени зависит от типа плат- формы, от системных настроек размещения разделяемых библиотек и от окружения (например, от значения переменной окружения LD_LIBRARY_PATH и других параметров). Возвращает None, если библиотеку не удалось оты- скать.
Внешние функции
Экземпляры разделяемых библиотек, созданные вызовом конструктора
CDLL()
, действуют как прокси-объекты, обеспечивающие доступ к содер- жимому библиотеки языка C. Чтобы обратиться к элементу библиотеки, достаточно просто использовать оператор доступа к атрибутам. Например:
>>>
1   ...   64   65   66   67   68   69   70   71   ...   82


написать администратору сайта