命名空间包内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
相关产品推荐
相关产品推荐

