Как избежать создания библиотеки C с моим пакетом python?
Я создаю пакет python, используя библиотеку C ctypes.
Я хочу сделать свой пакет переносимым (Windows, Mac и Linux).
Я нашел стратегию, используя build_ext
с pip
для создания библиотеки во время установки моего пакета. Он создает libfoo.dll
или libfoo.dylib
или libfoo.so
в зависимости от целевой платформы.
Проблема заключается в том, что мой пользователь должен установить CMake.
Существует ли другая стратегия, чтобы избежать строительства во время установки? Нужно ли связывать встроенные библиотеки в моем пакете?
Я хочу, чтобы мои пользователи выполняли pip install mylib
.
Изменить: спасибо комментарию @Dawid, я стараюсь сделать python wheel
с помощью команды python setup.py bdist_wheel
без каких-либо успехов.
Как я могу создать свое колесо python для разных платформ со встроенной библиотекой?
Изменить 2: Я использую python 3.4 и работаю в Mac OS X, но у меня есть доступ к компьютеру Windows и Linux-компьютеру
Ответы
Ответ 1
Вы, безусловно, идете по правильному пути в соответствии с моими исследованиями... Как говорит Дэниел, единственный вариант, который у вас есть, состоит в том, чтобы самостоятельно создавать и распространять свои двоичные файлы.
В общем, рекомендуемый способ установки пакетов хорошо описан в руководстве пользователя по упаковке. Я не буду повторять совет, потому что вы уже его уже нашли. Однако ключевой момент в том, что сообщество Python, в частности PyPA, пытается стандартизировать использование колеса платформы для пакетных расширений. К сожалению, на данный момент есть несколько проблем:
- Вы не можете создавать дистрибутивы для всех вариантов Linux, но вы можете создавать колеса для совместимого подмножества. Подробнее см. https://www.python.org/dev/peps/pep-0513/.
- советы по созданию расширений несколько неполны, что отражает отсутствие полного решения для двоичных дистрибутивов.
- Затем люди пытаются создать свою собственную библиотеку и распространять ее как файл данных, что путает setuptools.
Я думаю, вы попадаете в эту последнюю проблему. обходной путь заключается в том, чтобы заставить Distribution создать колесо платформы, переопределив is_pure(), чтобы всегда возвращать False. Однако вы можете просто сохранить свои исходные инструкции по сборке, и bdist_wheel должен его обработать.
Как только вы построили колесо, вам все равно нужно его распространять и, возможно, другие бинарные пакеты, которые он использует или использует. На данный момент вам, вероятно, нужно использовать один из рекомендуемых инструментов, таких как conda или прокси-сервер PyPI, например devpi для обслуживания ваших колес.
EDIT: Чтобы ответить на дополнительный вопрос о кросс-компиляции
Как описано здесь Python 2.6 и более поздние версии позволяют кросс-компиляцию для Windows 32/64-битных построений. Официальной поддержки других пакетов на других платформах не существует, и у людей было ограниченный успех, пытающихся это сделать. Вам действительно лучше строить изначально на каждой из ваших Linux/Mac/Windows сред.
Ответ 2
@rth и @PeterBrittain мне очень помогают. Здесь решение, которое я использую:
папка структуры:
setup.py
python_package/
lib/
libfoo.dylib
libfoo.dll
__init__.py
main.py
setup.py:
from setuptools import setup, dist
class BinaryDistribution(dist.Distribution):
def is_pure(self):
return False
setup(
name='python_package',
package_data={'python_package': ['lib/libfoo.dylib','lib/libfoo.dll']},
include_package_data=True,
distclass=BinaryDistribution,
packages=['python_package'],
)
main.py:
#!/usr/bin/env python
import platform
from ctypes import CDLL, c_char_p
import pkg_resources
sysname = platform.system()
if sysname == 'Darwin':
lib_name = "libfoo.dylib"
elif sysname == 'Windows':
lib_name = "libfoo.dll"
else:
lib_name = "libfoo.so"
lib_path = pkg_resources.resource_filename('python_package', 'lib/{}'.format(lib_name))
foo = CDLL(lib_path)
bar = foo.bar
bar.restype = c_char_p
bar.argtypes = [c_char_p]
print(bar('hello'))
построить колесо:
python setup.py bdist_wheel
Он создает специальное колесо формы rtfdoc-0.0.1-cp34-cp34m-macosx_10_10_x86_64.whl
, и пользователи Mac могут сделать простой pip install rtfdoc-0.0.1-cp34-cp34m-macosx_10_10_x86_64.whl
Это решение не совсем удовлетворительное:
- Думаю, мне все равно нужно создать Extension или посмотреть SCons для пользователей Linux.
- Обновление моего пакета будет затруднено из-за создания lib
- Я не знаю, как управлять .dll для 32-битных и 64-битных
Спасибо, я многому научился, и я понимаю, почему setup.py в Pillow или Psycopg2 огромны.
Ответ 3
Вы можете использовать cibuildwheel
для сборки колес на Travis CI и/или Appveyor для всех видов платформ и версий Python. Этот инструмент также может развернуть ваши колеса на PyPI или в другом месте.
Ответ 4
Я предпочитаю, чтобы мой пользователь установил cygwin/mingw32 или cmake и сделал pip install mylib
[...]. Я просто хочу пойти дальше и попытаться избежать установки CMake.
Что касается упаковки предварительно скомпилированных модулей python, см. полный ответ @Peter Brittain.
Теперь, предполагая, что у пользователя действительно установлен C-компилятор (будь то cygwin, conda в Windows или системный в Linux), и все, что вам нужно, - это избежать установки CMake, которая не имеет отношения к упаковке Python.
Вопрос в том, сколько функциональных возможностей CMake вы используете, и можно ли сделать то же самое с помощью упрощения управления альтернативами, см. связанные вопросы (1), (2) и т.д.
Изменить: В частности, я думал что-то вроде SCons, которое обеспечивает полную сборку но написанный на Python, поэтому его проще установить в дружественной Python среде, чем CMake, см. полное сравнение здесь. Дикая догадка (я никогда не использовал ее сам), но поскольку это чистый модуль python, вы могли бы установить SCons
как зависимость в вашем setup.py
и полностью автоматизировать сборку своего C-кода там, чтобы pip install mylib
делает все, что нужно. См. Также CMake2SCons, который может быть полезен.
Ответ 5
Если вы не хотите, чтобы пользователь создавал во время установки, вы должны предоставить предварительно построенный двоичный пакет, я не думаю, что любая другая стратегия возможна. Я слышал хорошие вещи о py2exe, но я не использую Windows, поэтому IDK. У меня были хорошие впечатления от miniconda, но для этого требуется небольшая дополнительная работа строить двоичные пакеты из pypi.