如何避免使用我的python包构建C库?

时间:2015-07-13 10:11:25

标签: python python-3.x cmake pip

我正在使用带有ctypes的C库构建python包。 我想让我的包可移植(Windows,Mac和Linux)。

我找到了一个策略,使用build_extpip在我的软件包安装过程中构建库。它会根据目标平台创建libfoo.dlllibfoo.dyliblibfoo.so

问题在于我的用户需要安装CMake。

是否存在避免在安装过程中构建的另一种策略?我是否必须在我的包中捆绑构建的库?

我希望让我的用户保持pip install mylib

修改:感谢@Dawid评论,我尝试使用命令python wheel制作python setup.py bdist_wheel但没有任何成功。

如何使用嵌入式库为不同平台创建我的python轮?

编辑2:我使用python 3.4并在Mac OS X上工作,但我可以访问Windows计算机和Linux计算机

5 个答案:

答案 0 :(得分:7)

根据我的研究,你肯定正走在正确的道路上......正如丹尼尔所说,你唯一的选择就是自己建立和分发二进制文件。

一般情况下,packaging user guide中详细介绍了安装软件包的推荐方法。我不会在那里重复建议,因为你已经清楚地发现了它。然而,关键点在于Python社区,特别是PyPA正在尝试使用platform wheels标准化打包二进制扩展。遗憾的是,此时存在一些问题:

  1. 您无法为所有Linux变体创建分发,但您可以为兼容子集构建轮子。有关详细信息,请参阅https://www.python.org/dev/peps/pep-0513/
  2. advice on building extensions有点不完整,反映出缺乏二进制分发的完整解决方案。
  3. 然后人们尝试构建自己的库并将其作为数据文件分发,这会混淆setuptools。
  4. 我认为你正在讨论最后一期。 workaround是通过重写is_pure()来强制分布构建平台轮,以便始终返回False。但是,您可以保留原始构建指令,bdist_wheel应该处理它。

    但是,一旦你构建了轮子,你仍然需要分发它,也许还需要它使用或使用它的其他二进制包。此时,您可能需要使用像recommended tools之类的conda或像devpi这样的PyPI代理来为您的车轮提供服务。

    编辑:回答有关交叉编译的额外问题

    正如所涵盖的here Python 2.6及更高版本允许对Windows 32/64位版本进行交叉编译。其他平台上的其他软件包没有正式支持,人们已经limited success尝试这样做了。您最好在每个Linux / Mac / Windows环境中本地构建。

答案 1 :(得分:3)

@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

这个解决方案并不完全令人满意:

谢谢,我学到了很多,而且我理解为什么Pillow或Psycopg2中的setup.py是巨大的

答案 2 :(得分:2)

您可以使用cibuildwheel在Travis CI和/或Appveyor上为各种平台和Python版本构建轮子。此工具还可以在PyPI或其他位置部署轮子。

答案 3 :(得分:1)

  

我更喜欢我的用户安装cygwin / mingw32或cmake并执行pip install mylib [...]。我只是想进一步尝试避免CMake安装

关于打包预编译的python模块,请参阅@Peter Brittain的完整答案。

现在,假设用户实际安装了C编译器(无论是cygwin,Windows上的conda还是Linux上的系统),而您想要的只是避免CMake安装,那与Python打包无关。

问题是您使用的CMake功能有多少,以及是否可以通过更易于管理的替代方案完成同样的事情,请参阅相关问题(1)(2)等。

编辑:特别是,我在思考SCons提供完整构建系统的内容,但是用Python编写,因此更容易在Python友好环境中安装比CMake,见full comparison here。一个疯狂的猜测(我自己从未使用过),但由于它是一个纯python模块,你可以将SCons设置为setup.py中的依赖项,并完全自动化C代码的构建在那里,pip install mylib完成所需的一切。另请参阅CMake2SCons包可能有用。

答案 4 :(得分:0)

如果您不希望用户在安装过程中进行构建,则必须提供预先构建的二进制包,我不认为任何其他策略是可行的。我已经听说过关于py2exe的好消息,但是我没有使用Windows这样的IDK。我对miniconda有很好的体验,但确实需要额外的工作build binary packages from pypi