【问题标题】:Prepare C-based Cython package to publish on pypi准备基于 C 的 Cython 包以在 pypi 上发布
【发布时间】:2018-09-03 09:28:56
【问题描述】:

我要创建 C 库,我想使用 Cython 创建 Python 包装器。

现在我已经编译并捆绑了 mylib.a 文件(C 文件),我想在 Cython 中包装我的库中的方法。

我成功创建了.pyx.pxd 文件,我可以使用python setup.py build_ext 命令构建它。当我尝试在 pypi 上发布它时出现了我的问题。如果我运行 setup.py,创建轮子并发布它,我可以从 pypi 下载它 - 但我无法运行 import mylib

我为此阅读了很多在线教程。他们中很少有人表明他们的 C 代码是在用户端编译的。我的代码库将由许多文件构成,我更愿意提供已经构建的 C 代码作为.a 文件。

我的文件结构(仅重要文件):

/ lib
    - mylib.a
    - *.h files (for mylib.a)
- setup.py
/ mylib
    - mylib.pyx
    - cmylib.pxd
    - __init__.py

我的__init__.py 文件(导入从 pip 下载的包后会在此处抛出错误):

from . import mylib

我的setup.py(仅重要参数 - 在我看来):

setup(name='mylib'
      packages=['mylib'],
      ext_modules = [Extension(
          name="mylib", 
          sources=["mylib/mylib.bycython.c"], 
          include_dirs = [numpy.get_include(), "lib/"],
          extra_objects=["lib/mylib.a"])],
        "build_ext": build_ext
      }
)

(我在python setup.py build_ext 之前使用mylib.pyx 中的cython 构建mylib.bycode.c。根据this 文章,它可以加快安装包的速度,并且不需要用户拥有相同的cython 版本。)

也许值得一提 - 在构建我的包之后,我得到了 mylib 的 .so 文件。如果我将它复制到/mylib 目录,那么我可以从父目录import mylib 并使用mylib.mylib.say_hello() 访问我的方法。但是它不适用于从 pip 安装的软件包(在其他 PC 上),我也不想使用 mylib.mylib

如果我应该提供更多信息 - 请告诉我。

编辑:

我在 GitHub 上的项目(我之前混淆了名称,所以这里是真实项目):https://github.com/franiis/statr-python

我想从statr.pyx 成功运行say_hello() 方法(其他方法可能不起作用)。

我知道代码有一些问题,但我想首先有工作核心来修复和更新所有内容。构建项目使用build_script.shupload_script.sh 创建轮子并发布它。

【问题讨论】:

  • 如何从 PyPI 安装? (下载 + python setup.py installpip install)。那个时候有什么错误信息吗? import mylib 上的任何错误(如果是,究竟是什么)?对于 Cython 包,您可以像您一样提供 pyx/pxd 文件或 c 文件。两者都应该工作。欲了解更多信息,请create a Minimal, Complete, and Verifiable example
  • @PierredeBuyl 感谢您的关注。我试过pip install <name>。我遇到了一些常见的错误 - 指向__init__.py 的第一行并说cannot install name 'mylib'。在这一点上,我的整个项目可以用作最小的例子。我添加了有问题的 github 链接。

标签: python cython pypi


【解决方案1】:

setup.py 中有几个问题。

  • setup.py 未编译链接到的库。这意味着它必须手动编译。
  • 链接到库是预编译的静态链接存档。这是不可移植的,除了用于构建它的确切版本的 GCC/glibc 之外,不能分发到任何东西。
  • setup.py 未构建 cython 扩展代码。对 .pyx/.pxd 的更改不会反映在包中。

尝试类似:

from setuptools import setup, find_packages, Extension
from Cython.Build import cythonize, build_ext

extensions = [Extension(
          name="statr._ext", 
          sources=["statr/_ext.pyx", "lib/mylib.c"],
          depends="lib/mylib.h",
          include_dirs=[numpy.get_include(), "lib/"]
]

setup(name='statr'
      packages=find_packages(),
      ext_modules=cythonize(extensions),
      build_ext: build_ext
      }
)

使用上述内容,扩展名将是statr._ext。 pyx 的名称应该是_ext.pyx

mylib.c 将通过setup.py 构建并链接到扩展程序。 mylib.c 所需的任何其他编译器指令都应添加到扩展中。

包名将是statr。例如,您应该从 _ext 导入您希望在其 __init__.py 的顶级 statrd 模块中可用的任何内容,例如

from ._ext import my_cython_function

【讨论】:

    猜你喜欢
    • 2019-02-06
    • 2018-12-23
    • 2016-07-25
    • 1970-01-01
    • 1970-01-01
    • 2014-03-27
    • 2021-08-14
    • 2018-05-12
    • 1970-01-01
    相关资源
    最近更新 更多