Публичные API Cython#
По состоянию на апрель 2020 года, следующие модули в SciPy предоставляют функциональность через публичный cdef Объявления Cython API:
scipy.linalg.cython_blasscipy.linalg.cython_lapackscipy.optimize.cython_optimizescipy.special.cython_special
Это использует Возможности совместного объявления Cython#15456
cdef элементы объявлены в *.pxd файлы, которые распространяются
вместе с соответствующими DLL/SO файлами в бинарных установках SciPy.
Application Binary Interface#
Использование этих возможностей в SciPy, однако, требует от разработчиков SciPy дополнительной осторожности в отношении поддержания стабильности двоичного интерфейса приложений (ABI). Это похоже на разработку библиотек на C и отличается от того, как обратная совместимость работает в чистом Python.
Основное отличие от Python происходит из-за того, что объявления в заголовочном файле .pxd файлы используются, когда код, написанный пользователями, скомпилированный, но они также должны соответствовать тому, что доступно в SciPy, когда пользовательский код импортировано.
Пользовательский код может быть скомпилирован с одной версией SciPy, а скомпилированный
бинарный файл (который использует двоичный интерфейс, объявленный в .pxd
файлы) могут использоваться с другой установленной версией SciPy на
системе. Если интерфейсы несовместимы, либо возникает
исключение, либо происходит повреждение памяти во время выполнения и сбой.
При импорте Cython проверяет, что сигнатуры функций в установленном файле SciPy SO/DLL соответствуют сигнатурам в .pxd файл, используемый пользователем во время компиляции, и вызывает исключение Python при несоответствии. Если код SciPy структурирован правильно (см. ниже), эта проверка выполняется только для функций, которые фактически импортируются в пользовательском коде.
Мы полагаемся на эту возможность для предоставления проверки безопасности во время выполнения, что упрощает пользователям обнаружение несовместимых версий SciPy через исключения Python вместо трудноотслеживаемых сбоев во время выполнения.
цель стабильности ABI#
SciPy стремится поддерживать стабильность ABI в коде Cython, в следующем смысле:
Бинарные файлы, полученные компиляцией пользовательского исходного кода с одной версией SciPy, совместимы с любой другой версией SciPy, с которой исходный код может быть скомпилирован.
Попытка использовать несовместимую версию SciPy во время выполнения приведет к исключению Python при импорте пользовательского модуля.
Попытка использовать несовместимую версию SciPy во время компиляции приведёт к ошибке Cython.
Это означает, что пользователи могут использовать любую совместимую версию SciPy для компиляции бинарных файлов, не обращая внимания на ABI, т.е.,
Совместимость ABI = совместимость API
Обратная/прямая совместимость Cython API будет обрабатываться с аналогичной политикой устаревания/удаления, как и для Python API, см. Устаревшие функции.
Реализация стабильности ABI в SciPy#
Следующие правила разработки Cython API в SciPy необходимы для поддержания указанной выше цели стабильности ABI:
Добавление нового
cdefобъявления (функции, структуры, типы и т.д.) разрешено.Удаление
cdefобъявления разрешено, но должен следовать общая политика устаревания/удаления.cdefобъявления функций может быть изменен.Однако изменения приводят к обратно несовместимому изменению API, которое ломает любой код, использующий измененную сигнатуру, и должен следовать общая политика устаревания/удаления.
cdefобъявления чего-либо другого (например,struct,enum, и типы) являются окончательный. Как только объявление становится доступным в публичном Cython API в выпущенной версии SciPy, он не должен быть изменен.Если изменения необходимы, их нужно выполнять путём добавления новых объявлений с разными именами и удаления старых.
cdefклассы это не разрешено в публичных API (TBD: обратная совместимость cdef классов требует дополнительного исследования, но не должна допускаться, когда мы не уверены)Для каждого публичного API-модуля (как в
scipy.linalg.cython_blas), используйте единый интерфейс.pxdфайл объявления.Файл объявления публичного интерфейса не должен содержать
cimportутверждения. Если это так, проверка сигнатур Cython будет проверять все импортированные функции, а не только те, которые используются пользовательским кодом, так что изменение одной из них нарушает весь API.Если необходимы структуры данных, предпочитать непрозрачные структуры в публичном API. Объявления интерфейсов не должны содержать никаких объявлений членов структур. Выделение, освобождение и доступ к атрибутам структур данных должны выполняться с помощью функций.
Устаревание публичных Cython API#
Чтобы устареть публичную функцию Cython API, например:
# scipy/something/foo.pxd
cdef public int somefunc()
# scipy/something/foo.pyx
cdef public int somefunc():
return 42
вы можете добавить использование scipy._lib.deprecation.deprecate_cython_api
функция для выполнения устареваний в конце соответствующего
.pyx файл:
# scipy/something/foo.pyx
cdef public int somefunc():
return 42
from scipy._lib.deprecation import deprecate_cython_api
import scipy.something.foo as mod
deprecate_cython_api(mod, "somefunc", new_name="scipy.something.newfunc",
message="Deprecated in Scipy 1.5.0")
del deprecate_cython_api, mod
После этого модули Cython, которые cimport somefunc, будет выдавать
DeprecationWarning во время импорта.
Нет способа устаревания структур данных и типов Cython. Однако их можно удалить после удаления всех функций API, которые их используют, прошедших цикл устаревания.
Целые модули Cython могут быть устаревшими аналогично модулям Python, путём выдачи DeprecationWarning на верхнем уровне.