求助:安装暴露C++类的Cython模块后,无法在其他.pyx文件中cimport
问题根源
Cython的cimport逻辑和Python的import不同,除了需要编译好的扩展模块外,还要求:
- 每一层要被
cimport的包目录下必须存在__init__.pxd文件(作用类似Python的__init__.py,用于Cython识别包结构) .pxd文件必须在Cython的搜索路径中.pxd中引用的C头文件必须在C/C编译器的搜索路径中
修复步骤
1. 补全包层级的__init__.pxd文件
在对应目录下新建两个空的__init__.pxd文件,修改后项目结构如下:
├── cytest │ ├── __init__.pxd # 新增 │ ├── cywrappers │ │ ├── __init__.pxd # 新增 │ │ ├── cynode.pxd │ │ └── cynode.pyx │ └── hpp │ └── node.hpp └── setup.py
2. 修正setup.py的打包配置
修改package_data字段,确保所有.pxd、.hpp文件都会被安装到目标环境的site-packages目录下:
from setuptools import setup, find_packages, Extension from Cython.Distutils import build_ext import numpy as np setup( name = "pycytest", packages=find_packages(include=['cytest', 'cytest.*']), # 修正package_data匹配子目录下的所有必要文件 package_data={ "cytest": ["*.pxd", "hpp/*.hpp"], "cytest.cywrappers": ["*.pxd", "*.pyx"] }, zip_safe=False, ext_modules= [Extension("cytest.cywrappers.cynode", sources = ["cytest/cywrappers/cynode.pyx"], language="c++", extra_compile_args=["-O3", "-std=c++11"], include_dirs=["./cytest/hpp/", np.get_include()])], cmdclass = {'build_ext': build_ext} )
修改后重新执行pip install .安装模块。
3. 正确编写cimport语句并指定搜索路径
首先执行以下代码获取当前Python环境的site-packages路径:
import sysconfig print(sysconfig.get_path('purelib'))
假设输出路径为/path/to/site-packages,则Jupyter中的%%cython块写法如下:
%%cython --cplus -I/path/to/site-packages -I/path/to/site-packages/cytest/hpp # 正确的cimport写法,和Python包路径保持一致 from cytest.cywrappers cimport cynode # 测试使用C++类 cdef cynode.Node c_node = cynode.Node(10, 3.14) print(c_node.ID, c_node.value)
可选优化
如果需要频繁在其他Cython项目中引用该模块,可以在cytest/__init__.py中添加获取头文件路径的工具函数:
import os def get_include(): return os.path.dirname(os.path.abspath(__file__))
后续编译其他Cython扩展时,直接在include_dirs中传入cytest.get_include()和f"{cytest.get_include()}/hpp"即可,不需要手动写死路径。
内容的提问来源于stack exchange,提问作者boris
相关产品推荐
相关产品推荐

