You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Poetry+Cython构建跨平台通用Python Wheel包?

问题描述

我正在使用Poetry v1.4.1和Cython 3.0.5,我的包中包含需要编译的.pyx文件。若使用pyximport而非预编译,导入耗时极长;但通过poetry build(代码如下)构建时,生成的并非版本与平台无关的通用Wheel包my_package-1.0.0-py3-none-any.whl,而是特定的my_package-1.0.0-cp39-cp39-manylinux_2_31_x86_64.whl。

请问是否有办法构建全平台通用的Wheel包?能否在Wheel包安装时进行cythonize/编译C文件?


相关代码

pyproject.toml(部分)

...
[tool.poetry.build]
generate-setup-file = false
script = 'build.py'

[build-system]
requires = ["poetry-core", "Cython", "numpy"]
build-backend = "poetry.core.masonry.api"

build.py

import os
import shutil
from distutils.core import Distribution
import warnings

if os.environ.get("NO_BUILD", False):
    exit(0)

try:
    from Cython.Build import build_ext, cythonize
    import numpy

    ext_modules = cythonize("my_package/**/*.pyx", output_dir="build", include_path=["dmcommon"],
                            build_dir="build", aliases={'NUMPY': numpy.get_include()})
    dist = Distribution({"ext_modules": ext_modules})
    cmd = build_ext(dist)
    cmd.ensure_finalized()
    cmd.run()

    # Move compiled near origin files.
    for output in cmd.get_outputs():
        relative_extension = os.path.relpath(output, cmd.build_lib)
        relative_output_folder = os.path.dirname(relative_extension)
        os.makedirs(relative_output_folder, exist_ok=True)
        shutil.copyfile(output, relative_extension)
except Exception as ex:
    warnings.warn(f"Failed to build Cython extensions: {ex}")

解决方案

1. 构建全平台通用Wheel包(安装时编译)

要实现安装时自动编译Cython代码,需要调整构建流程,不在poetry build阶段预编译,而是把.pyx文件打包进Wheel,让pip在用户安装时完成编译。具体步骤:

修改pyproject.toml

  • 移除自定义build.py的配置,让Poetry自动生成setup文件,或改用setuptools作为构建后端:
[tool.poetry]
name = "my_package"
version = "1.0.0"
# 其他元信息...

[tool.poetry.dependencies]
python = "^3.7"
numpy = "^1.21"
# 其他依赖...

[tool.poetry.build]
generate-setup-file = true  # 启用自动生成setup.py

[build-system]
requires = ["poetry-core>=1.0.0", "Cython>=3.0.5", "numpy>=1.21"]
build-backend = "poetry.core.masonry.api"

手动编写setup.py(可选,精细控制编译逻辑)

如果Poetry自动生成的setup文件无法满足需求,可手动创建setup.py,用setuptools处理Cython扩展:

from setuptools import setup
from Cython.Build import cythonize
import numpy

setup(
    name="my_package",
    version="1.0.0",
    ext_modules=cythonize("my_package/**/*.pyx", include_path=[numpy.get_include()]),
    include_dirs=[numpy.get_include()],
)

同时修改pyproject.toml的构建后端:

[build-system]
requires = ["setuptools", "wheel", "Cython", "numpy"]
build-backend = "setuptools.build_meta"

这样构建出的通用Wheel会包含.pyx文件和编译配置,用户安装时pip会自动调用Cython编译代码,生成适配其平台的二进制文件。

2. 原流程生成平台特定Wheel的原因

你当前的build.py在poetry build阶段就完成了Cython代码的编译,生成了适配当前构建环境的二进制扩展,因此打包出的Wheel会带有平台标签,只能在对应平台使用。

注意事项

  • 用户安装环境需具备C编译器(如GCC、MSVC),否则编译会失败。若要兼容无编译器的环境,可同时发布通用Wheel和多平台预编译Wheel。
  • 可用cibuildwheel工具自动化构建多平台预编译Wheel,同时保留通用Wheel选项。

内容的提问来源于stack exchange,提问作者EZLearner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 10:10:55