Документация Python неофициальный перевод

cporting.md

185 строк · 7.6 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/2.6/howto/cporting.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Портирование модулей расширения на 3.089| автор: | Benjamin Peterson |10| --- | --- |1112Аннотация1314Хотя изменение C-API не было одной из целей Python 3.0, многие изменения на уровне Python сделали невозможным сохранение API 2.x нетронутым. Фактически, некоторые изменения, такие как объединение [`int()`](https://python-all.ru/2.6/library/functions.html#int) и [`long()`](https://python-all.ru/2.6/library/functions.html#long), более очевидны на уровне C. Этот документ стремится задокументировать несовместимости и способы их обхода.1516## Условная компиляция1718Самый простой способ компилировать только часть кода для 3.0 – проверить, что `PY_MAJOR_VERSION` больше или равно 3.1920```c21#if PY_MAJOR_VERSION >= 322#define IS_PY3K23#endif24```2526Отсутствующие функции API можно заменить псевдонимами на их эквиваленты в условных блоках.2728## Изменения в API объектов2930Python 3.0 объединил некоторые типы со схожими функциями, чётко разделив другие.3132### Унификация str/unicode3334Тип [`str()`](https://python-all.ru/2.6/library/functions.html#str) (функции `PyString_*` в C) в Python 3.0 эквивалентен типу [`unicode()`](https://python-all.ru/2.6/library/functions.html#unicode) (`PyUnicode_*`) в версии 2.x. Старый 8-битный строковый тип стал `bytes()`. Python 2.6 и новее предоставляют заголовочный файл совместимости, `bytesobject.h`, который отображает имена `PyBytes` на `PyString`. Для наилучшей совместимости с 3.0 следует использовать `PyUnicode` для текстовых данных и `PyBytes` для двоичных. Также важно помнить, что `PyBytes` и `PyUnicode` в 3.0 не взаимозаменяемы, в отличие от `PyString` и `PyString` в 2.x. Следующий пример показывает наилучшие практики в отношении `PyUnicode`, `PyString` и `PyBytes`.3536```c37#include "stdlib.h"38#include "Python.h"39#include "bytesobject.h"4041/* пример текста */42static PyObject *43say_hello(PyObject *self, PyObject *args) {44    PyObject *name, *result;4546    if (!PyArg_ParseTuple(args, "U:say_hello", &name))47        return NULL;4849    result = PyUnicode_FromFormat("Hello, %S!", name);50    return result;51}5253/* просто пересылка */54static char * do_encode(PyObject *);5556/* пример с байтами */57static PyObject *58encode_object(PyObject *self, PyObject *args) {59    char *encoded;60    PyObject *result, *myobj;6162    if (!PyArg_ParseTuple(args, "O:encode_object", &myobj))63        return NULL;6465    encoded = do_encode(myobj);66    if (encoded == NULL)67        return NULL;68    result = PyBytes_FromString(encoded);69    free(encoded);70    return result;71}72```7374### Унификация long/int7576В Python 3.0 есть только один целочисленный тип. На уровне Python он называется [`int()`](https://python-all.ru/2.6/library/functions.html#int), но на самом деле соответствует типу [`long()`](https://python-all.ru/2.6/library/functions.html#long) из 2.x. В C-API функции `PyInt_*` заменены их аналогами `PyLong_*`. Лучший способ действий – использовать функции `PyInt_*`, которые объявлены как псевдонимы `PyLong_*` в `intobject.h`. Абстрактные API `PyNumber_*` также можно использовать в некоторых случаях.7778```c79#include "Python.h"80#include "intobject.h"8182static PyObject *83add_ints(PyObject *self, PyObject *args) {84    int one, two;85    PyObject *result;8687    if (!PyArg_ParseTuple(args, "ii:add_ints", &one, &two))88        return NULL;8990    return PyInt_FromLong(one + two);91}92```9394## Инициализация и состояние модуля9596Python 3.0 имеет переработанную систему инициализации модулей расширения. (См. [**PEP 3121**](https://python-all.ru/2.6/howto/cporting.html).) Вместо хранения состояния модуля в глобальных переменных, его следует хранить в структуре, специфичной для интерпретатора. Создание модулей, которые корректно работают как в 2.x, так и в 3.0, является сложной задачей. Следующий простой пример показывает, как это сделать.9798```c99#include "Python.h"100101struct module_state {102    PyObject *error;103};104105#if PY_MAJOR_VERSION >= 3106#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))107#else108#define GETSTATE(m) (&_state)109static struct module_state _state;110#endif111112static PyObject *113error_out(PyObject *m) {114    struct module_state *st = GETSTATE(m);115    PyErr_SetString(st->error, "something bad happened");116    return NULL;117}118119static PyMethodDef myextension_methods[] = {120    {"error_out", (PyCFunction)error_out, METH_NOARGS, NULL},121    {NULL, NULL}122};123124#if PY_MAJOR_VERSION >= 3125126static int myextension_traverse(PyObject *m, visitproc visit, void *arg) {127    Py_VISIT(GETSTATE(m)->error);128    return 0;129}130131static int myextension_clear(PyObject *m) {132    Py_CLEAR(GETSTATE(m)->error);133    return 0;134}135136static struct PyModuleDef moduledef = {137        PyModuleDef_HEAD_INIT,138        "myextension",139        NULL,140        sizeof(struct module_state),141        myextension_methods,142        NULL,143        myextension_traverse,144        myextension_clear,145        NULL146};147148#define INITERROR return NULL149150PyObject *151PyInit_myextension(void)152153#else154#define INITERROR return155156void157initmyextension(void)158#endif159{160#if PY_MAJOR_VERSION >= 3161    PyObject *module = PyModule_Create(&moduledef);162#else163    PyObject *module = Py_InitModule("myextension", myextension_methods);164#endif165166    if (module == NULL)167        INITERROR;168    struct module_state *st = GETSTATE(module);169170    st->error = PyErr_NewException("myextension.Error", NULL, NULL);171    if (st->error == NULL) {172        Py_DECREF(module);173        INITERROR;174    }175176#if PY_MAJOR_VERSION >= 3177    return module;178#endif179}180```181182## Другие варианты183184Если вы пишете новый модуль расширения, возможно, стоит рассмотреть [Cython](https://python-all.ru/2.6/howto/cporting.html). Он транслирует язык, похожий на Python, в C. Создаваемые им модули расширения совместимы с Python 3.x и 2.x.185