Cython编译的C扩展:ImportError: 动态模块未定义init函数。

50
我刚刚使用Cython将我的C库的一部分编译成了扩展,作为一个“概念证明”。我设法解决了代码中的问题(除了const正确性问题之外),最终成功构建了扩展。但是,当我尝试导入新创建的扩展时,出现了以下错误:
ImportError: dynamic module does not define init function 

我做错了什么,该怎么修复这个问题?

我在Ubuntu 10.04上使用Cythn 0.11.2和Python 2.6.5。


2
你用什么命令行生成了 .c 文件?你是如何编译它的? - tito
9个回答

77

我发现经常出现这个问题的原因是,在使用distutils安装文件编译代码时,.pyx基本名称与扩展名不匹配,例如:

ext = Extension(name='different', sources=['cython_ext.pyx']) # Won't work

为避免问题,扩展名必须完全相同,例如在此情况下是cython_ext

很好的调用。有人知道为什么这个有效,而不同的名称却无效吗? - dinkelk
2
@Dologan,谢谢,这很有帮助!我想让你的回答更完整:name 可以像 make.something.useful.cython_ext 一样嵌套。重点是模块名(最后一个点后的单词)应与源文件的名称相同。我猜在你的回答中放入这样的正面例子会更有帮助。 - Charlie
谢谢你。令人惊奇的是,这么多年过去了,还没有一个错误信息可以解释这个问题。 - Neil

36

看起来这是Cython中的一个bug/特性。我也遇到了同样的问题,但只需添加以下内容即可:

STUFF = "Hi"

将文件开头加上.pyx后缀,问题就消失了。看起来,如果没有全局初始化(通过cinit或设置全局变量),则所需的初始化代码不会生成。


6
哇,我简直不敢相信那真的管用了,但它修复了我的库中相同的漏洞。 - Rick
1
也适用于我。 - John Walthour

2

这是一个非常晚的评论,但我认为这个答案可能与cdef class有关,而不是模块,所以可能不是报告的问题。然而,我意识到在这个阶段很难知道你正在解决什么问题... - DavidW

1
在我的情况下,我回答得非常晚。我在一个运行python2的终端中意外地调用了cython,而在另一个python环境的终端上尝试使用生成的库时,使用了python3。在所有地方使用相同的python版本解决了这个问题。

0
同样是一个晚回答...但我一直回到这个特定的问题。这可能与Dologan所解决的名称不匹配的问题有关。
在我的情况下发生了什么是,我正在调整我已经成功运行的示例,并得到了“模块未定义init函数”的错误。通过使用(例如)
nm -m build/lib.macosx-10.9-x86_64-2.7/myproj.so
验证了这一点。在此命令的输出中,我搜索了“init”并找到了
000000000000c0d0 (__TEXT,__text) external _initexample 我已经从我的setup.py和.pyx文件中删除了所有“example”的实例,但即使从site-packages中删除扩展名,删除构建和dist文件夹等,这种情况仍然存在。最后,我发现从我的.pyx文件生成的.cpp文件仍在引用示例中的类名。一旦重新运行了我的setup.py,导入就可以工作,确实.so文件包括
000000000000c0a0 (__TEXT,__text) 外部 _initmyproj

0

我也遇到了这个问题。请确保您的Cython文件至少包含以下内容之一:

  • 一个普通的Python def
  • 一个普通的Python类(不是cdef class
  • 一行Python初始化代码,例如a=None或日志加载

否则,Cython将无法生成所需的PyInit例程以加载模块,因此该模块将无法被Python导入。


即使是一个空的 pyx 文件,我也无法让它失败。如果你有任何不起作用的例子,将其报告为 bug 可能会很有用,链接为 https://github.com/cython/cython/issues。 - DavidW

-1
这可以通过为您的函数添加文档字符串来解决。

没有任何理由可以帮助。你能解释一下吗? - steco

-1

我曾经遇到过同样的错误,后来通过在“专用控制台中执行”模式下运行主要的.py脚本解决了问题。该选项位于工具-首选项-运行中。


-1

我通过以下方式解决了它:

def cinit(self): pass

希望有所帮助。

这听起来像是你在使用cdef class时遇到了问题,而这个问题是关于模块的。如果这是正确的话,我会感到惊讶。另外请注意,Python中使用双下划线__表示特殊方法,而不是cinit - DavidW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接