You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Cython打包带自模块的模块时对象丢失问题求助

问题解决:Cython子模块结构下对象无法访问及模块冲突问题

核心问题分析

  1. Foobar类无法访问:错误将Extension命名为foo.bar,但bar.pyx实际属于foo.bar包下的子模块bar,导致编译后的扩展模块与foo.bar目录包冲突。Python导入时优先加载目录下的__init__.py,而非Cython编译的模块,因此Foobar未被导出。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 15:25:09