当前位置: 首页 > 知识库问答 >
问题:

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

岳鸿畴
2023-03-14

我正在构建一个Python包,使用一个带有ctype的C库。我想让我的包便携(Windows,Mac和Linux)。

我找到了一个策略,在安装包的过程中,使用build\u extpip来构建库。它创建libfoo。dlllibfoo。动态库libfoo。因此取决于目标的平台。

这个问题是我的用户需要安装Cmake。

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

我想让我的用户继续执行pip安装mylib

编辑:感谢@Dawid comment,我正在尝试使用命令python setup制作一个python轮子。py b单轮未成功。

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

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


共有3个答案

吕峰
2023-03-14

您可以使用ciBuildWheers在Travis CI和/或Appveyer上为各种平台和Python版本构建轮子。这个工具也可以在PyPI或其他地方部署你的轮子。

岳劲
2023-03-14

@rth和@PeterBrittain对我帮助很大。以下是我使用的解决方案:

结构文件夹:

setup.py
python_package/
    lib/
        libfoo.dylib
        libfoo.dll
    __init__.py
    main.py

设置。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安装rtfdoc-0.0。1-cp34-cp34m-macosx_10_10_x86_64。whl

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

  • 我想我仍然需要为linux用户创建一个扩展或查看SCons。
  • 更新我的包会很困难,因为lib的生产
  • 我不知道怎么管理. dll为32位和64位

谢谢你,我学到了很多,我明白为什么。枕头上的py或Psycopg2都是巨大的

堵雅健
2023-03-14

根据我的研究,你肯定走对了路。。。正如Daniel所说,您唯一的选择就是自己构建和分发二进制文件。

一般来说,包装用户指南中很好地介绍了安装包的推荐方式。我不会在那里重复建议,因为你显然已经找到了。然而,这里的关键点是Python社区,特别是PyPA,正试图标准化使用平台轮打包二进制扩展。可悲的是,目前有几个问题:

  1. 您不能为所有Linux变体创建发行版,但是您可以为兼容的子集构建轮子。详见https://www.python.org/dev/peps/pep-0513/。
  2. 关于构建扩展的建议有些不完整,反映了二进制分布缺乏完整的解决方案。
  3. 然后,人们试图构建自己的库并将其作为数据文件分发,这会混淆setupool。

我认为你击中了最后一期。一种解决方法是通过重写is_pure()来强制分发构建平台轮,以始终返回False。然而,您可以保留原始的构建说明,bdist_wheel应该处理它。

但是,一旦您构建了轮子,您仍然需要分发它以及它使用或使用的其他二进制软件包。此时,您可能需要使用推荐的工具之一(如conda)或PyPI代理(如devpi)为您的控制盘提供服务。

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

如本文所述,Python 2.6及更高版本允许对Windows 32/64位版本进行交叉编译。在其他平台上没有对其他软件包的正式支持,人们尝试这样做的成功有限。您最好在每个Linux/Mac/Windows环境上进行本机构建。

 类似资料:
  • 我的Dockerfile有点像 每次构建新映像时,都必须重新安装依赖项,这在我的区域可能会非常慢。 我想到的一种缓存已安装的软件包的方法是用以下更新的图像覆盖我的基本图像: 所以下次我用这个Dockerfile构建时,我的/base已经安装了一些包。 但这种解决方案有两个问题: 并不总是可以覆盖基本映像 随着新图像的分层,基本图像变得越来越大 那么,我可以用什么更好的解决方案来解决这个问题呢? 关

  • 问题内容: 我的Dockerfile就像 每次构建新映像时,都必须重新安装依赖项,这在我所在的地区可能非常慢。 我想到的已安装软件包的一种方法是用较新的图像覆盖该图像,如下所示: 因此,下一次我使用此Dockerfile进行构建时,我/基础已经安装了一些软件包。 但是此解决方案有两个问题: 并非总是可以覆盖基本图像 随着新图像的叠加,基础图像变得越来越大 那么我可以使用什么更好的解决方案来解决这个

  • 问题内容: 我有一个客户端库,在该客户端库中对我的REST服务进行http远程调用,然后返回给客户,该客户正在调用我的库,其中包含从REST服务获得的响应以及所有错误(如果包装了任何错误)围绕对象。 这是我的枚举类: 这是我的枚举类: 如您所见,在我的课堂上我有很多领域,因此我有一个很长的构造器,每次当我做一个对象的时候都会有很大的联系。将来我可能会有更多的字段,但目前只有这些字段。 有什么更好的

  • 问题内容: 这看起来很丑。可选选项的优点在这里完全消失了。我读到应该使用或代替。但是,如果我更换每个吸气剂,真的有好处吗? 与 您知道这里的一些常见或最佳做法吗? 问题答案: 您可以使用 关键是仅在可选函数不为空时才评估映射函数,否则结果将保留为空。如果可选为空,将返回。

  • 我被困在编写Python Selenium脚本中,似乎无法令人满意地解决我得到的这个StaleElementReistrceException。 我加载了我的页面,然后单击一个按钮,打开一个表单,允许用户向订单中添加新的信用卡。在这一点上,我做了一个WebDriverWait来暂停脚本,直到这个表单上的Save按钮变为可见。此时,重新创建页面对象,因为它已更改,我的目的是填充字段并保存卡片。 问题

  • 问题内容: 我正在尝试通过从客户端向服务器发送密钥和随机数来认证用户。 我的代码未向我显示客户端的响应。执行下面的代码时,我得到了一个空指针异常。 问题答案: 解决大多数问题的固定步骤: 阅读堆栈跟踪以确定哪一行代码引发NPE 在该行代码处设置一个断点 使用调试器,在遇到断点时,确定该行中的对象引用是 弄清楚为什么引用该文件(到目前为止,这是唯一实际的困难部分) 解决根本原因(也可能很困难)

  • 问题内容: 我有两个简单的Java代码。第一个将恒定功率定义为power = a.pow(b); 第二个将恒定功率定义为power = BigInteger.ONE.shiftLeft(b) 在命令行中设置内存标志- Xmx1024m,第一个代码可以正常工作,但是第二个代码却出现错误:java.lang.OutOfMemoryError:Java堆空间 我的问题:我应该在第二个代码中更改什么以避免

  • 问题内容: 我有一个用于将文本添加到现有.doc文件中的代码,它将通过使用apache POI将其另存为另一个名称。 以下是到目前为止我尝试过的代码 以下是我得到的 我已经添加了与此对应的所有jar文件,但仍然找不到解决方案。我对apache poi是陌生的,所以请帮我提供一些解释和示例。谢谢 问题答案: 从我对问题的评论中复制: 看起来您需要Apache POI发行版中的poi-ooxml-sc