Как создать модуль расширения Python, совместимый с PEP384, и упаковать его с правильным тегом ABI3?

mymodule.c начинается следующим образом:

      #define PY_SSIZE_T_CLEAN
#define Py_LIMITED_API 0x03070000 
#include "Python.h"

Сборка без ошибок и предупреждений. Тем не менее, результирующий файл называется

      mymodulename.cpython-37m-x86_64-linux-gnu.so

Команда сборки:

      $ python setup.py build

Когда я выдаю вместо этого

      $ pip wheel .

расширение, содержащееся в колесе, называется так же, и, следовательно, колесо также не имеет тега ABI3.

Я ожидал имя файла с abi3 или подобным, как указано в PEP 425.

Мои исследования до сих пор разочаровывали. Я просмотрел PEP 384 и 425, документы и соответствующие руководства на docs.python.org, в частности его C/API и distutils, документы от PYPA, документы по setuptools, wheel и pip — безрезультатно.

Файл /modules/xxmodule.c, содержащийся в текущем исходном дистрибутиве Python, представляет просто исторический интерес.
Что мне здесь не хватает?

1 ответ

Это зависит от бэкэнда; не все бэкенды сборки поддерживают PEP 384.

Например, при использовании чистого (так

      from distutils.core import setup

setup(...)

), нет возможности изменить суффикс расширения; вот почему мне пришлось задать вопрос об изменении правил именования Cython для файлов .so несколько лет назад. Но вы не должны использовать чистый distutilsв любом случае в настоящее время, так что этот раздел только ради полноты.

Если вы используете setuptools, вы должны пройти py_limited_api=Trueпри создании Extensionобъекты. Пример:

      from setuptools import setup, Extension


setup(
    ...,
    ext_modules=[
        # this extension will have the SOABI suffix, e.g.
        # cpython-37m-darwin or cpython-39-x86_64-linux-gnu etc.
        Extension("foo", ["foo.c"]),
        # this extension will have the `abi3.so` suffix
        Extension("bar", ["bar.c"], py_limited_api=True),
    ],
)

Бонус: если вы создаете модули расширения из кода Rust и используете setuptools_rust, создание расширений, совместимых с PEP 384, теперь также возможно, начиная с версии 0.11.4:

      from setuptools import setup
from setuptools_rust import RustExtension


setup(
    ...,
    rust_extensions=[
        RustExtension("foo.rust", py_limited_api=True, features=["pyo3/abi3"]),
    ],
)

: построение правильного тега колеса

Когда я выпускаю

       $ pip wheel .

расширение, содержащееся в колесе, называется так же, и, следовательно, колесо также не имеет тега ABI3.

Тег колеса — это несколько другая история; он не зависит от имен расширений, которые он упаковывает. Чтобы установить ограниченный ABI, при построении колеса обычным способом можно было бы выдать

      $ python setup.py bdist_wheel --py-limited-api=cp37

Полученное колесо будет иметь имя <pkg>-<ver>-cp37-abi3-<platform>.whl.

Однако это не будет работать с pip wheelпоскольку вы не можете передавать параметры подкоманде. Таким образом, вы можете сохранить его в:

      # setup.cfg
[bdist_wheel]
py_limited_api = cp37

При работе pip wheel .в настоящее время, bdist_wheelподберет вариант из setup.cfgи соберите правильное имя колеса.

Другие вопросы по тегам