我正在使用带有ctypes的C库构建python包。 我想让我的包可移植(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计算机
答案 0 :(得分:7)
根据我的研究,你肯定正走在正确的道路上......正如丹尼尔所说,你唯一的选择就是自己建立和分发二进制文件。
一般情况下,packaging user guide中详细介绍了安装软件包的推荐方法。我不会在那里重复建议,因为你已经清楚地发现了它。然而,关键点在于Python社区,特别是PyPA正在尝试使用platform wheels标准化打包二进制扩展。遗憾的是,此时存在一些问题:
我认为你正在讨论最后一期。 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)
结构文件夹:
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。