Как установить привязку Python к библиотеке C++

Представим, что нам дан готовый исходный код библиотеки на C++ с именем MyAwesomeLib. Цель состоит в том, чтобы предоставить часть его возможностей python, поэтому мы создаем оболочку, используя swig, и сгенерировали пакет python с именем PyMyAwesomeLib.

Структура каталогов теперь выглядит так

root_dir
|-src/
|-lib/
|    |- libMyAwesomeLib.so
|    |- _PyMyAwesomeLib.so
|-swig/
|    |- PyMyAwesomeLib.py
|-python/
     |- Script_using_myawesomelib.py

Все идет нормально. В идеале все, что нам нужно сделать дальше, это скопировать lib/*.so swig/*.py и python/*.py в соответствующий каталог в site-packages способом pythonic, т. е. используя

python setup.py install

Однако я очень запутался, пытаясь достичь этой простой цели, используя setuptools и distutils. Оба инструмента выполняют компиляцию расширений Python через внутреннюю систему, где исходный файл, флаги компилятора и т. д. передаются с использованием setup(ext_module=[Extension(...)]). Но это нелепо, так как MyAsesomeLib имеет полностью функционирующую систему сборки, основанную на makefile. Перенос логики, встроенной в make-файлы, был бы избыточной и совершенно ненужной работой.

После некоторых исследований кажется, что осталось два варианта: я могу либо переопределить setuptools.command.build и setuptools.command.install, чтобы использовать существующий make-файл и напрямую скопировать результаты, либо я могу каким-то образом сообщить setuptools об этих файлах и попросить его скопировать их во время установки. Второй способ более привлекателен, но именно он вызывает у меня больше всего головной боли. Я безуспешно пробовал следующие варианты

  • package_data и include_package_data не работают, потому что файлы *.so не находятся под контролем версий и не входят ни в один пакет.
  • data_files не работает, так как файлы включаются только при запуске python setup.py sdist, но игнорируются при python setup.py install. Это противоположно тому, что я хочу. Файлы .so не должны быть включены в исходный дистрибутив, а должны быть скопированы на этапе установки.
  • MANIFEST.in не удалось по той же причине, что и data_files.
  • eager_resources тоже не работает, но если честно я не знаю разницы между eager_resources и data_files или MANIFEST.in.

Я думаю, что это на самом деле обычная ситуация, и я надеюсь, что есть простое решение. Любая помощь будет принята с благодарностью.


person James    schedule 22.03.2015    source источник
comment
Удалось ли вам решить эту проблему? У меня очень похожая ситуация и мне пригодится ваш опыт. Ваше здоровье!   -  person jorgeh    schedule 12.10.2016
comment
Это, вероятно, мертво, но я также хотел бы знать ваше решение. Вы нашли удовлетворительное решение?   -  person muma    schedule 25.09.2017
comment
Почти три года! Я тоже в такой же ситуации.   -  person Jey    schedule 01.02.2018


Ответы (1)


Перенос логики, встроенной в make-файлы, был бы избыточной и совершенно ненужной работой.

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

Портирование на самом деле было не так уж и плохо. distutils понимает расширения SWIG, но это было реализованы довольно бессистемно с их стороны. Запуск SWIG создает файлы Python, и текущий порядок сборки предполагает, что все файлы Python были учтены до запуска build_ext. Это было не слишком сложно исправить, но это раздражает, что они утверждают, что поддерживают SWIG, не упоминая об этом. Distutils пытается быть кросс-платформенным при компиляции, поэтому его использование все же имеет преимущество.

Если вы не хотите портировать всю систему сборки, используйте менеджер пакетов системы. Многие сложные библиотеки делают это (но они также стараются изо всех сил с setup.py). Например, чтобы получить numpy и lxml в Ubuntu, нужно просто сделать: sudo apt-get install python-numpy python-lxml. Нет пипа.

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

Если вы попытаетесь пойти по пути setuptools, я столкнулся с одной фатальной ошибкой: зависимостями.

Например, если вы распространяете проект на основе SWIG, вам понадобится libpython. Если его нет, возникает такая ошибка:

#include <Python.h>
error: File not found

Это довольно бесполезно для обычного пользователя.

Хуже того, если вам требуется разделяемая библиотека, но пользовательская библиотека устарела, пользователь может столкнуться с некоторыми сумасшедшими ошибками. Вы зависите от их компилятора C++, который выводит удобные для Google сообщения об ошибках, чтобы они могли понять это.

Долгосрочным решением было бы заставить setuptools/distutils лучше обнаруживать библиотеки, отличные от python, надеюсь, так же хорошо, как драгоценный камень Ruby. Мне пришлось в значительной степени свернуть свой собственный. Например, в этом setup.py я работаю на вы можете увидеть несколько функций вверху, которые я взломал вместе для обнаружения зависимостей (до сих пор не работает на всех системах... определенно не на Windows).

person sciencectn    schedule 12.04.2015
comment
Я ценю ваш вклад. К сожалению, в моем пакете много нетривиальных зависимостей. Подготовить предварительно скомпилированный пакет для нескольких распространенных систем управления пакетами было бы лучшим вариантом на данный момент. Я надеюсь, что сообщество Python исправит эту проблему в ближайшем будущем. - person James; 25.06.2015