同包内Cython导入报错求助(已尝试相关方案无效)
解决Cython中
cimport my_package.b引发的ImportError: No module named my_package.b问题 我先梳理下你的问题场景:你用Cython构建包时,编译过程没报错,但运行测试代码时遇到了模块导入错误,改用普通import b却能正常运行。结合你的目录结构和代码,我来帮你分析问题并给出解决思路。
首先看你的目录结构,这里有个关键错误:你的__init__.py放在了项目根目录,而不是my_package文件夹内。Python要求一个目录必须包含__init__.py才能被识别为可导入的包,这是导致cimport失败的核心原因之一。
先给你修正后的正确目录结构:
. ├── my_package │ ├── __init__.py # 移到这个位置! │ ├── a.pyx │ ├── b.pyx │ ├── b.pxd │ └── test.py # 也可以移到根目录,看你需求 └── setup.py
接下来是具体的解决步骤:
1. 修正包结构与导入逻辑
- 把根目录的
__init__.py移动到my_package文件夹内,让Python把my_package识别为合法包。 - 调整
test.py的导入方式:- 如果把
test.py留在my_package内,使用相对导入:from . import a c = a.a() - 如果把
test.py移到项目根目录,使用绝对导入:from my_package import a c = a.a()
- 如果把
2. 完善setup.py的包配置
你的setup.py缺少对包的声明,导致编译后的扩展模块无法被Python正确识别为包的一部分。修改后的setup.py如下:
from distutils.core import setup from distutils.extension import Extension from Cython.Build import cythonize import numpy extensions = [ Extension("my_package.a", ["my_package/a.pyx"] ), Extension("my_package.b", ["my_package/b.pyx"] ) ] for e in extensions: e.cython_directives = {"embedsignature": True} setup( name = "preprocess", ext_modules = cythonize(extensions), packages=["my_package"], # 添加这行,明确声明要打包的目录 )
3. 确保Cython能找到.pxd文件
当你使用cimport my_package.b时,Cython需要定位到对应的b.pxd文件。如果还是有问题,可以在Extension中添加include_dirs参数,把项目根目录加入搜索路径:
extensions = [ Extension( "my_package.a", ["my_package/a.pyx"], include_dirs=["."] # 让Cython能找到根目录下的my_package包 ), Extension("my_package.b", ["my_package/b.pyx"]) ]
最后验证步骤
- 按照上面的修改调整目录和代码
- 重新执行编译命令:
python setup.py build_ext --inplace - 运行test.py,此时
cimport my_package.b应该能正常工作了。
为什么改用import b能运行?因为当你在my_package目录下运行test.py时,Python会把当前目录加入模块搜索路径,所以import b能找到同目录下的b模块,但这不是规范的包内导入方式,而cimport需要依赖包的结构来定位.pxd文件,所以必须先把包结构修正正确。
内容的提问来源于stack exchange,提问作者user2660324
相关产品推荐
相关产品推荐

