使用Cython打包带自模块的模块时对象丢失问题求助
问题解决:Cython子模块结构下对象无法访问及模块冲突问题
核心问题分析
- Foobar类无法访问:错误将Extension命名为
foo.bar,但bar.pyx实际属于foo.bar包下的子模块bar,导致编译后的扩展模块与foo.bar目录包冲突。Python导入时优先加载目录下的__init__.py,而非Cython编译的模块,因此Foobar未被导出。 - foo成为自身子模块:Extension命名错误导致编译生成的扩展文件与目录包重名,引发Python导入机制混淆,出现异常的子模块引用。
具体修复步骤
1. 修正setup.py中的Extension配置
将Extension名称改为foo.bar.bar,并统一管理编译参数:
from setuptools import Extension, setup from Cython.Build import cythonize ext_modules = [ Extension( "foo.bar.bar", sources=["foo/bar/bar.pyx", "src/bar.c"], include_dirs=["src"] ), ] setup( ext_modules=cythonize(ext_modules, language_level=3), packages=["foo", "foo.bar"] )
注:把
src/bar.c和include_dirs移到Extension参数中,比在pyx文件中用注释更直观,也便于统一管理。
2. 修改foo/bar/__init__.py导出Foobar
在foo/bar/__init__.py中添加以下内容,将Cython模块中的Foobar导入到包命名空间:
from .bar import Foobar __all__ = ["Foobar"]
3. 重新编译安装
执行编译命令:
python setup.py build_ext --inplace
4. 验证修复结果
进入Python交互环境测试:
>>> import foo.bar >>> dir(foo.bar) ['Foobar', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'bar'] >>> fb = foo.bar.Foobar() >>> fb.double() 714
此时foo.bar中已能正常访问Foobar类,且dir(foo)中不再出现异常的foo子模块。
补充:确保C函数定义正确
检查src/bar.h和src/bar.c的内容是否符合预期:
src/bar.h:
#ifndef BAR_H #define BAR_H int double_int(int num); #endif
src/bar.c:
#include "bar.h" int double_int(int num) { return num * 2; }
内容的提问来源于stack exchange,提问作者popeye
相关产品推荐
相关产品推荐

