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

命名空间包内Cython扩展打包:setup.py无法识别*.pxd文件

问题:打包包含命名空间包的Cython扩展时,.pxd文件未被识别处理

我正在打包一个包含命名空间包内Cython扩展的项目,文件夹结构如下:

.
├── namespace_package
│   └── package
|       ├── extension.pxd
|       ├── extension.pyx
│       └── __init__.py
└── setup.py

我的setup脚本如下:

from setuptools import setup
from setuptools.extension import Extension

# factory function
def my_build_ext(pars):
    # import delayed:
    from setuptools.command.build_ext import build_ext as _build_ext
    # include_dirs adjusted:
    class build_ext(_build_ext):
        def finalize_options(self):
            _build_ext.finalize_options(self)
            # Prevent numpy from thinking it is still in its setup process:
            __builtins__.__NUMPY_SETUP__ = False
            import numpy
            self.include_dirs.append(numpy.get_include())
    #object returned:
    return build_ext(pars)

extensions = [Extension(namespace_package.package.extension, ['namespace_package\\package\\extension.pyx']]

setup(
    cmdclass={'build_ext' : my_build_ext},
    setup_requires=['cython', 'numpy'],
    install_requires=['cython', 'numpy'],
    packages=['namespace_package.package'],
    ext_modules=extensions
)

我采用了延迟导入numpy和cython的技巧,但extension.pxd文件未被找到或处理,导致其中的声明无法使用并出现对应错误,请问如何正确配置setup以识别并处理所有文件?


解决方案

这个问题主要有几个关键点需要调整,我来一步步帮你解决:

1. 修正Extension的名称参数

你当前的Extension名称写法有误,应该用字符串格式的全限定模块名,而不是直接引用模块(此时模块还未被安装或导入)。修改后的Extension定义如下:

extensions = [Extension(
    'namespace_package.package.extension',  # 改为字符串格式的全限定名
    ['namespace_package/package/extension.pyx']  # 建议用正斜杠保证跨平台兼容
)]

2. 明确包含.pxd文件到包中

setuptools默认不会自动识别Cython的.pxd文件,需要通过package_data参数明确指定要包含的文件类型,确保这些文件被打包到安装包中,Cython编译时才能找到对应的声明:

在setup()函数中添加以下配置:

package_data={
    'namespace_package.package': ['*.pxd'],
},
include_package_data=True,  # 确保package_data配置生效

3. 用cythonize处理扩展(推荐)

使用Cython提供的cythonize函数可以让Cython更智能地处理.pyx和.pxd文件的依赖关系,自动查找同目录下的关联文件。

首先导入cythonize:

from Cython.Build import cythonize

然后修改扩展的定义:

extensions = cythonize([
    Extension(
        'namespace_package.package.extension',
        ['namespace_package/package/extension.pyx']
    )
])

4. 完整的修改后setup.py

整合以上所有调整,最终的setup.py代码如下:

from setuptools import setup
from setuptools.extension import Extension
from Cython.Build import cythonize

# factory function
def my_build_ext(pars):
    # import delayed:
    from setuptools.command.build_ext import build_ext as _build_ext
    # include_dirs adjusted:
    class build_ext(_build_ext):
        def finalize_options(self):
            _build_ext.finalize_options(self)
            # Prevent numpy from thinking it is still in its setup process:
            __builtins__.__NUMPY_SETUP__ = False
            import numpy
            self.include_dirs.append(numpy.get_include())
    #object returned:
    return build_ext(pars)

extensions = cythonize([
    Extension(
        'namespace_package.package.extension',
        ['namespace_package/package/extension.pyx']
    )
])

setup(
    cmdclass={'build_ext': my_build_ext},
    setup_requires=['cython', 'numpy'],
    install_requires=['cython', 'numpy'],
    packages=['namespace_package.package'],
    ext_modules=extensions,
    package_data={
        'namespace_package.package': ['*.pxd'],
    },
    include_package_data=True
)

额外提示

  • 测试打包前,可以先运行python setup.py build_ext --inplace本地编译扩展,快速验证.pxd文件是否被正确识别,有没有编译错误。
  • 路径使用正斜杠可以保证Windows和Linux/macOS的跨平台兼容性,避免切换系统时出现路径问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:06:31