Python嵌套包中C扩展模块无法导入问题求助
解决嵌套包中C扩展模块的ImportError问题
问题根源
你遇到的ImportError: cannot import name 'dummyext' from 'rootpack'本质是C扩展模块的初始化函数名称与模块的完整限定名不匹配,导致Python无法正确识别并注册该扩展模块到rootpack包下。
当C扩展模块属于嵌套包(如rootpack.dummyext)时,Python会寻找名为PyInit_<完整模块名>的初始化函数(其中点号替换为下划线,即PyInit_rootpack_dummyext),但你的原代码中初始化函数是PyInit_dummyext,与预期名称不符,因此导入失败。
修复步骤
1. 修改C扩展的初始化函数及模块定义
更新dummy.c中的两处关键内容:
- 将模块定义的名称改为完整限定名
"rootpack.dummyext"(确保模块的__name__正确) - 将初始化函数名从
PyInit_dummyext改为PyInit_rootpack_dummyext
修改后的dummy.c代码:
#include <Python.h> #include <numpy/arrayobject.h> static PyObject* dummy_method(PyObject* self, PyObject* args) { npy_int rows = 3; npy_int cols = 4; npy_intp dims[2] = {rows, cols}; PyObject* arr_obj = PyArray_ZEROS(2, dims, NPY_INTP, 0); int* arr_data = PyArray_DATA(arr_obj); for(int i = 0; i < rows; ++i) { for(int j = 0; j < cols; ++j) { arr_data[i*cols + j] = i+j; } } return arr_obj; } static PyMethodDef dummyext_methods[] = { {"dummy_method", dummy_method, METH_VARARGS, "Returns a dummy array"}, {NULL, NULL, 0, NULL} }; static struct PyModuleDef dummyext_module = { PyModuleDef_HEAD_INIT, "rootpack.dummyext", // 改为完整模块名 NULL, -1, dummyext_methods }; PyMODINIT_FUNC PyInit_rootpack_dummyext(void) // 匹配完整模块名的初始化函数 { PyObject* module = PyModule_Create(&dummyext_module); import_array(); return module; }
2. 调整setup.py配置(二选一即可)
方式一:不使用ext_package,直接指定完整模块名
保持原setup.py的ext_modules配置不变,仅确保Extension的名称是rootpack.dummyext:
import setuptools import numpy PACKAGE_NAME = 'rootpack' setuptools.setup( name=PACKAGE_NAME, version="0.0.1", description="Testing extension module", packages=[PACKAGE_NAME], ext_modules = [ setuptools.Extension( 'rootpack.dummyext', ['ext/dummy.c'], extra_compile_args=["-std=c99"], include_dirs=[numpy.get_include()], ), ], install_requires=[ 'numpy', ], )
方式二:使用ext_package简化模块名配置
启用ext_package参数,并将Extension的名称改为相对模块名dummyext,此时setuptools会自动为其添加rootpack前缀:
import setuptools import numpy PACKAGE_NAME = 'rootpack' setuptools.setup( name=PACKAGE_NAME, version="0.0.1", description="Testing extension module", packages=[PACKAGE_NAME], ext_package=PACKAGE_NAME, # 启用扩展包前缀 ext_modules = [ setuptools.Extension( 'dummyext', # 仅写相对模块名 ['ext/dummy.c'], extra_compile_args=["-std=c99"], include_dirs=[numpy.get_include()], ), ], install_requires=[ 'numpy', ], )
3. 测试注意事项
使用tox/cibuildwheel/pytest测试时,务必确保:
- 测试环境中已正确安装构建后的包(而非直接运行源码目录)
- tox配置中包含
pip install .或pip install -e .步骤,保证模块结构与安装后的一致
内容的提问来源于stack exchange,提问作者Vagrant Nexus
相关产品推荐
相关产品推荐

