【问题标题】:How to structure and distribute Pybind11 extension with stubs?如何使用存根构建和分发 Pybind11 扩展?
【发布时间】:2021-04-28 19:02:52
【问题描述】:

我正在尝试创建和分发(使用 pip)具有 Python 代码的 Python 包,以及使用 Pybind11(使用 Visual Studio 2019)编译为 .pyd 文件的 C++ 代码。我还想包含 .pyi 存根文件,用于 VScode 和其他编辑器。我找不到太多关于正确执行此操作的文档。

我希望喜欢能够像往常一样通过 pip 安装包,并像普通 Python 包一样编写 from mymodule.mysubmodule import myfunc 等,包括自动完成、类型注释、VScode 智能感知等使用.pyi 文件我会写。

我的 C++ 代码位于多个 cpp 和头文件中。它使用了一些标准库,一些外部库(例如boost)。它定义了一个模块和两个子模块。我希望能够在 Windows 和 Linux 以及 x86 和 x64 上分发它。我目前的目标是 Python 3.9 和 c++17 标准。

我应该如何构建和分发这个包?我是否包含 c++ 源文件,并创建一个类似于Pybind11 example 的 setup.py?如果是这样,我如何包含外部库?以及如何构建 .pyi 存根文件?这是否意味着试图安装我的包的人也需要一个 c++ 编译器?

或者,我应该将我的 c++ 编译为每个平台和架构的 .pyd/.so 文件吗?如果是这样,有没有办法指定通过 pip 安装哪个?再说一遍,我将如何构建 .pyi 存根?

【问题讨论】:

    标签: python c++ pybind11 python-extensions


    【解决方案1】:

    生成.pyi 存根

    pybind11 issue 提到了一些工具(12)来为二进制模块生成存根。可能还有更多,但我不知道其他人。不幸的是,两者都远非完美,因此您可能仍需要手动检查和调整生成的存根。

    .pyi 存根的分布

    在更正存根之后,您只需将那些.pyi 文件与py.typed 指示文件一起包含在您的分发中(例如,在轮子中或作为源文件),或者将它们作为独立包单独分发(例如mypackage-stubs)。

    造轮子

    Wheels 允许您的库的用户以二进制形式安装它,即无需编译。 Wheels 使用较旧的编译器以兼容更多的系统/平台,因此您可能会在使用 C++17 库时遇到一些麻烦。 (C++11 已经够老了,轮子应该没有问题)。

    各种平台的造轮子很繁琐,pybind11 的python_example 使用cibuildwheels 包来做,如果你已经在使用CI,我会推荐这条路线。

    如果目标平台缺少轮子,pip 将尝试从源安装。这需要您已经安装编译器和第 3 方库。

    也许康达?

    如果您的设置很复杂并且需要许多第三方库,则可能值得编写 conda recipe 并使用 conda-forge 生成软件包的二进制版本。 Conda 优于 pip,因为它也可以管理非 python 依赖项。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-06
      • 2017-12-16
      • 2020-08-28
      • 1970-01-01
      • 2018-06-18
      • 2018-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多