Как стать автором
Обновить

Комментарии 26

Если ли какие-либо библиотеки, фреймворки для разработки модулей Python на C/C++?

пару раз использовал SWIG

Boost.Python, PySide(Qt идёт в комплекте если нужен), PyBind вообще их довольно много, но это всё для плюсов.

ctypes посмотрите - прекрасно и просто работает, совместим с numpy, несколькими комментариями ниже я ссылочки на гитхаб привел.

ctypes — это слишком низкоуровневая штука. Подходит, если уже есть сильная библиотека. Если же нужно написать сколько-нибудь сложный модуль и можно писать на C++, то лучше взять pybind11. Из того, чем пользовался, это самый удобный вариант.

С помощью этой библиотеки можно легко писать функции и классы, которые импортируются сразу как родные без какой-либо питоновской обвязки. Поддерживается очень много всего, есть удобная трансляция типов между языками.

Си нынче не в моде, нужно писать на Rust.

Кстате, а можно модули для питона писать на Rust?

Одна из самых развитых и протестированных в проде библиотек

https://github.com/PyO3/PyO3

Могу посоветовать серию статей (за моим авторством) на эту тему - https://dygalo.dev/blog/rust-for-a-pythonista-3/

В последней части там довольно много деталей о том как такие модули собирать, тестировать и дебажить.

Может просто с Python на Golang перейти и все?
Начать можно с написания C-Shared DLL на Go и вызова их из Python...

Конкретно на числах Фибоначчи @lru_cache должно дать похожие результаты

тогда уж похожую технику можно использовать и для С версии ;-)
конечно придеться по потеть .....
но можно написать на плюсах и прокинуть в С ;-), конечно будет чуть больше кода чем готовый декоратор в пайтоне , но эфект не меньше и
думаю в конечном итоге разрыв даже увеличиться ;-)

Можно написать стандартную C библиотеку и подключить с помощью ctypes, который прекрасно поддерживается numpy. В реальности еще OpenMP нужен для распараллеливания по ядрам или OpenMPI по хостам. Вот пример такой библиотеки на гитхабе: https://github.com/mobigroup/gis-snippets/blob/master/geomed3d/geomed3dv3.py А еще можно заменить бинарные расширения на numba плюс dask или joblib, получив практически такую же скорость вычислений и распараллеливание. Пример на гитхабе: https://github.com/mobigroup/gis-snippets/blob/master/Synthetic%20Model%20Inversion/basic.ipynb

Сорри за первую ссылку, которая не кликабельна - чертов новый редактор комментариев то кусок текста убивает, то вот ссылки калечит, что на планшете, что на ноутбуке. Ссылка: https://github.com/mobigroup/gis-snippets/tree/master/geomed3d Тут лежит набор файлов .c и .h с библиотекой на C, питоновская «обертка» к модулю geomed3dv4.py и Jupyter notebook с примером geomed3dv4.ipynb

int для Фибоначчи - это несколько плохой пример. Он переполняется очень быстро, эти чуть больше 40 значений проще вообще тогда предвычислить и запихнуть в константы. Прямо в Питон.

Более того, даже unsigned long long рано или поздно может переполниться. И что тогда будете делать? А в Python собственная реализация int практически "резиновая". Да, это несёт накладные расходы. Тем не менее, я бы демонстрировал мощь Python C-API не на таком примере, а на примере POSIX threads. Это, пожалуй, самый большой камень в огороде Питона из-за GIL.

То есть, с помощью C-extension можно приделать модуль, который полностью отвечает требованиям внутреннего API Python (то есть, принимает и отдаёт в функциях Python-объекты), а внутри делает, например, так:

{
  PyThreadState *_save;
  Py_UNBLOCK_THREADS
  do_some_jobs_in_threads();
  Py_BLOCK_THREADS
}

Конечно, это не единственное, чего можно достичь. Среди дополнительных плюсов использования C-extension:

  • Более точное и аккуратное управление памятью, потому что int в интерпретаторе - это всегда громоздкая структура, а нам, например, требуется несколько 4-битных полей, которые можно плотно упаковать в структуру без выравнивания

  • Операции над примитивами в C всегда будут быстрее, чем операции над "примитивами" в интерпретаторе. Желающие могут убедиться, как всё сложно в интерпретаторе, попробовав реализовать 1-в-1 небольшую портянку на 50 строк Python-функции, но в виде C-extension и без использования сишных примитивов. Все эти PyCFunction, PyObject_GetAttribute, возня с INCREF/DECREF. В общем, всё то, что делал бы интерпретатор, только ручками. А затем скомпилировать и сравнить производительность. Выигрыш, если и будет, придётся в микроскоп разглядывать.

Некоторую часть вышеперечисленного (включая, кстати, работу с потоками исполнения) можно покрыть с помощью Cython. Но он далёк от совершенства и при этом генерирует очень грязный и избыточный код. Как прототип для MVP подойдёт, но потом всё равно оптимизировать и доводить до ума.

А вот чего действительно очень не хватает: это внятной документации по awaitable в C-API.

int в интерпретаторе - это всегда громоздкая структура, а нам, например, требуется несколько 4-битных полей, которые можно плотно упаковать в структуру без выравнивания

А какой практический смысл оптимизировать хранение одного int? Если у вас больше одного int (или не int) - есть массивы numpy, к этому блоку памяти можно получить прямой доступ из внешней библиотеки, с помощью cython и так далее. Выделяем память с помощью инициализации массива numpy, работаем с областью памяти из библиотеки и из питона читаем результат. Что вы тут оптимизировать собрались? Более того, с помощью numba можно практически такую же скорость получить для python кода.

Ну, во-первых, обычно, конечно же, надо не один int оптимизировать, а десятки или сотни всяких структур, указателей и указателей на указатели. Во-вторых, обработка из Питона результатов работы библиотеки превращается в боль, если мы говорим о хоть какой-то кросс-платформенности. На одной платформе без выравнивания не бывает, на другой указатели 32-битные, на третьей 64-битные, на четвертой еще какие-нибудь приколы. Всё это превращается в тонны if-else и подобных частоколов стреляющих в ногу ружей, и всё равно получается масса работы с int интерпретатора, а это постоянные boxing/unboxing.

Все намного проще, на самом деле. Вот как с помощью ctypes передать указатель на int массив numpy во внешнюю библиотеку: ndpointer(ctypes.c_int32, flags="C_CONTIGUOUS") и сами данные x.astype(ctypes.c_int32). В библиотеке на C объявляем этот аргумент функции как int32_t *x и работаем с этим массивом. Можно переданные массивы и читать и модифицировать, а потом в питоне прочитать измененную версию. Никаких проблем с кроссплатформенностью нет - нужно правильно указать типы данных, к примеру, int32. Если же вы привыкли везде писать int вместо int32, то вы сами стреляете себе в ногу. Аналогично, можно и с библиотекой на фортране легко работать. Ну, на фортране я сам давно уж не пишу, а вот читать код и подключать библиотеки порой приходится (особенно в языке R любят фортран библиотеки без единого комментария и с кучей «магии», для переноса научных вычислений на питон приходится разбираться).

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

A = p * (1+r/n) ** nt

Но вы правы, это оффтоп. Для вопросов больше подходит https://qna.habr.com

Раз уж вы ответили, а разве nt не нужно представить как произведение n * t ? И в скобки поставить, так как у степени приоритет?

С задачкой разобралась. Возник новый вопрос: почему не работает import turtle в pyscripter для python? выдает ошибку.

К сожалению, это не имеет отношения к обсуждению статьи. Лучше задайте вопрос на Stackoverflow.

Мне кажется, сравнивать Python c Java глупо, ведь они работают практически одинаково.

Что же в них одинакового?

Зарегистрируйтесь на Хабре, чтобы оставить комментарий