python - 如何在 Python 包中包含共享 C 库

标签 python makefile setuptools

我有一个依赖共享库的项目。从一开始就明确:共享库是一个纯 C 库,而不是 Python 库。为了简单起见,我创建了一个名为 pkgtest 的小型演示项目,我将引用它。

所以需要做的是:运行 Makefile 来编译库并将编译后的共享库(此处称为 libhello.so)文件放置在可以从依赖的 Python 包中访问的位置.

到目前为止,我最好的猜测是将 makefile 作为预安装例程运行,复制 packages 目录中的 libhello.so 文件并将其添加到 package_data 参数中安装脚本。安装后,共享库将放置在 site-packages/pkgtest/ 目录中,可以从模块访问。

包目录结构很简单:

pkgtest/
  src/
     libhello.c
     libhello.h
     Makefile
  pkgtest/
    __init__.py
    hello.py
  setup.py

我的 setup.py 看起来像这样:

setup.py

import subprocess
from setuptools import setup
from distutils.command.install import install as _install


class install(_install):
    def run(self):
        subprocess.call(['make', 'clean', '-C', 'src'])
        subprocess.call(['make', '-C', 'src'])
        _install.run(self)


setup(
    name='pkgtest',
    version='0.0.1',
    author='stefan',
    packages=['pkgtest'],
    package_data={'pkgtest': ['libhello.so']},
    cmdclass={'install': install},
)

Makefile 实际上构建库并将其复制到我的 python 包的目录中。

src/Makefile

all: libhello.so

libhello.o: libhello.c
        gcc  -fPIC -Wall -g -c libhello.c

libhello.so: libhello.o
        gcc -shared -fPIC -o libhello.so libhello.o
        cp libhello.so ../pkgtest/libhello.so

clean:
        rm -f *.o *.so

所以 hello.py 实际上所做的就是加载库并调用打印一些文本的 hello 函数。但为了完整起见,我将在此处显示代码:

pkgtest/hello.py

import os
import ctypes

basedir = os.path.abspath(os.path.dirname(__file__))
libpath = os.path.join(basedir, 'libhello.so')

dll = ctypes.CDLL(libpath)

def say_hello():
    dll.hello()

所以这实际上可行,但我不喜欢这种方法的是共享库位于 Python 包的目录中。我认为将它放在某种中央库目录中会更好,例如 /usr/lib/。但是对于这个,安装时需要 root 权限。是否有人对此类问题有一些经验,并愿意分享解决方案或有用的想法。会很棒。

最佳答案

您可以使用 manylinux 创建一个包含共享库并适用于(几乎)任何 Linux 发行版的 Python 包.

The goal of the manylinux project is to provide a convenient way to distribute binary Python extensions as wheels on Linux. This effort has produced PEP 513 which defines the manylinux1_x86_64 and manylinux1_i686 platform tags.

一般程序是:

  1. 在 manylinux 团队提供的其中一个 docker 容器中构建外部库和 Python 包 (参见 python-manylinux-demo)
  2. 运行 auditwheel repair将您的包所依赖的外部共享库复制到 Python 轮中,相应地设置 RPATH。

参见 .travis.ymlbuild-wheels.shpython-manylinux-demo 存储库中作为示例。

关于python - 如何在 Python 包中包含共享 C 库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45121352/

相关文章:

python - 如何从 python3 中的 xgboost 模型中提取决策规则(特征拆分)?

c++ - CFLAGS=-std=c++11 -O3 -Wall -pedantic 在 makefile 中未被识别

python - 将python项目打包为多个目录

makefile patsubst 多个表达式

docker - 如何通过命令行在Debian上构建嵌入式Atmel Studio项目

python - 在 Ubuntu 上通过 virtualenv 中的设置工具安装 Numpy 时出错

setuptools - readthedocs和setuptools scm版本错误

python - 在没有 proxy_pass 的情况下使用 Nginx 服务 Django 站点

python - django 中关系模型放在哪里

python - 我安装了一个 Python 程序,但找不到它的所有源代码