Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Бинарные модули для Python

Бинарные модули для Python

Дмитрий Жильцов (ЦИАН, Системный Архитектор) @ Moscow Python Conf 2017
"Я расскажу про малоосвещенную тему – бинарные модули в питоне. В данном докладе речь будет идти о следующем:
1. Когда необходимы бинарные модули и зачем они нужны. В каких случаях их лучше использовать, а в каких нет. Как спроектировать грамотную архитектуру общения кода на Python с бинарным расширением.
2. Технологии и инструменты для разработки бинарных расширений. Минусы и плюсы каждого.
Доклад рассчитан на разработчиков, у которых есть потребность в разработке своих бинарных модулей, но не хватает опыта".
Видео: https://conf.python.ru/binarnye-moduli-dlya-python/.

Moscow Python Meetup

October 20, 2017
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. Б И Н А Р Н Ы Е М О

    Д У Л И В P Y T H O N
  2. О ЦИАН - 7 млн покупателей и арендаторов в месяц

    - 75% москвичей знают о нас - 8x разработка за 2014-2017
  3. Зачем нужны бинарные модули? • Python не так быстр как

    хочется • GIL – боль • Переиспользование логики из существующих библиотек • Скрытие исходников (спорно)
  4. Когда бинарные расширения действительно нужны? • Когда оптимизировали код и

    архитектуру, но производительности не хватает • Обильно используем multi threading для простых операций • Заведомо тяжелые операции • Образовалась стабильная логика работы модуля
  5. 5 золотых правил • Экспортировать функции • Использовать классы обертки

    • Нельзя напрямую передавать аргументы из Python в extension • Нужно дополнительно учитывать сборку мусора • Явно определять агрументы экспортируемой функции
  6. Native C/C++ Extension Плюсы • Родная технология • Легко интегрируется

    в сборку проекта • Наибольшее кол-во документации • Позволяет создавать свои типы данных Минусы • Большой порог входа • Знание С • Boost.Python • Segmentation Fault :( • Сложности в Debug
  7. #include <Python.h> static PyObject*addList_add(PyObject* self, PyObject* args){ PyObject * listObj;

    if (! PyArg_ParseTuple( args, "O", &listObj)) return NULL; long length = PyList_Size(listObj); int i, sum =0; // Опустим реализацию return Py_BuildValue("i", sum); }
  8. for(i = 0; i < length; i++){ // Получаем элемент

    из списка // он также Python-объект PyObject* temp = PyList_GetItem(listObj, i); // Мы знаем, что элемент это целое число // приводим его к типу C long long elem = PyLong_AsLong(temp); sum += elem; }
  9. // Документация static char addList_docs[] = "add( ): add all

    elements of the list\n"; // Регистрируем функции модуля static PyMethodDef addList_funcs[] = { {"add", (PyCFunction)addList_add, METH_VARARGS, addList_docs}, {NULL, NULL, 0, NULL} };
  10. PyInit_addList(void){ PyObject *module = PyModule_Create(&mdef); if (module == NULL) return

    NULL; PyModule_AddStringConstant(module, "__author__", “Bruse Lee<[email protected]>"); PyModule_AddStringConstant(module, "__version__", "1.0.0"); return module; }
  11. SWIG Плюсы • Стабильная технология • Большое кол-во документации •

    Абстрагирует от привязки к Python Минусы • Долгая настройка • Знание С • Segmentation Fault :( • Сложности в Debug • Сложность интеграции в сборку проекта
  12. Cython Плюсы • Популярная технология • Довольно стабильно • Легко

    интегрируется в сборку проекта • Хорошая документация Минусы • Свой синтаксис • Знание С • Segmentation Fault :( • Сложности в Debug
  13. CTypes Плюсы • Родная технология • Легко использовать в коде

    • Легко реализовать кросплатформенность • Можно использовать практически любой язык Минусы • Несет накладные расходы • Сложности в Debug
  14. from ctypes import * #load the shared object file adder

    = CDLL('./adder.so') #Calculate factorial res_int = adder.fact(4) print("Fact of 4 = " + str(res_int))
  15. Rust Плюсы • Безопасный язык • Мощные статические гарантии правильности

    поведения • Легко интегрируется в сборку проекта (PyO3) Минусы • Большой порог входа • Долгая настройка • Сложности в Debug • Документации мало • В некоторых случаях - накладные расходы
  16. #![feature(proc_macro)] #[macro_use] extern crate pyo3; use pyo3::prelude::*; /// Module documentation

    string 1 #[py::modinit(_addList)] fn init(py: Python, m: &PyModule) -> PyResult<()> { py_exception!(_addList, EmptyListError); /// Function documentation string #[pyfn(m, "run", args="*", kwargs="**")] fn run_py(_py: Python, args: &PyTuple, kwargs: Option<&PyDict>) -> PyResult<()> { run(args, kwargs) } #[pyfn(m, "add")] fn add(_py: Python, py_list: &PyList) -> PyResult<i32> { let mut sum : i32 = 0; match py_list.len() { /// Some code Ok(sum) } Ok(()) }
  17. #[pyfn(m, "add", py_list="*")] fn add(_py: Python, py_list: &PyList) -> PyResult<i32>

    { match py_list.len() { 0 =>Err(EmptyListError::new("List is empty")), _ => { let mut sum : i32 = 0; for item in py_list.iter() { let temp:i32 = match item.extract() { Ok(v) => v, Err(_) => { let err_msg: String = format!("List item {} is not int", item); return Err(ItemListError::new(err_msg)) } }; sum += temp; } Ok(sum) } } }
  18. • Native C/C++ Extension • Знаем или не боимся изучить

    С • Важен результат а не скорость разработки • Минимум инструментария • SWIG • То же что и С-extension • Проблемы при сборке, но увеличивается скорость разработки • Cython • Новый язык • Малый порог входа • Скорость разработки • Ctypes • Быстро, дешево, сердито • Иногда вообще не надо пичего писать • Накладные расходы • Rust • Новый язык с наркоманским синтаксисом • Безопасность и гарантии • Не несет накладных расходов
  19. • https://github.com/zaabjuda/moscowpythonconf2017 https://docs.python.org/3/extending/building.html • http://cython.org • https://docs.python.org/3.6/library/ctypes.html • http://www.swig.org •

    https://www.rust-lang.org/en-US/ • https://github.com/PyO3 • https://www.youtube.com/watch?v=5-WoT4X17sk • https://packaging.python.org/tutorials/distributing-packages/#platform- wheels
  20. ?