【问题标题】:ImportError: dynamic module does not define init function (initfizzbuzz)ImportError:动态模块没有定义初始化函数(initfizzbuzz)
【发布时间】:2020-10-27 22:33:52
【问题描述】:

我尝试编译fizzbuzz.c,以便通过python 导入它。对于构建fizzbuzz.c,我使用了python setup.py build_ext -i

构建后,我尝试导入fizzbuzz.c,但出现以下错误。 我该如何解决这个问题?

错误

>>> import fizzbuzz
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: dynamic module does not define init function (initfizzbuzz)

fizzbuzz.c

#include <stdio.h>

void fizzbuzz(int n){

    for (int i=1; i <= n; i++){
        if (i % 3 == 0 && i % 5 ==0){
            printf("fizzbuzz %d \n", i);
        }
        else if (i % 3 == 0){
            printf("fizz %d \n", i);
        }
        else if(i % 5 == 0){
            printf("buzz %d \n", i);
        }
    }
}

setup.py

from distutils.core import setup, Extension
module = Extension('fizzbuzz', ['fizzbuzz.c'])
setup(
      name='fizzbuzz',
      version='1.0',
      ext_modules=[module],
)

【问题讨论】:

  • 这远不是一个合适的 Python 扩展模块。
  • 我建议你先阅读C-API tutorial
  • 对于后代,如果您在同一目录中有两个文件fizzbuzz.so 和一个(正确编写的 ctypes 包装器)fizzbuzz.py,并且您尝试使用import fizzbuzz,Python 似乎更喜欢@987654333 @,它也会产生这个错误信息。
  • 将 C 扩展从 python 2 移植到 3:docs.python.org/3/howto/cporting.html

标签: python c python-c-api


【解决方案1】:

在使用boost::python 时,如果模块名与编译后的.so 文件名不同,也会出现此错误。例如:

hello.cpp

#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
using namespace std;
using namespace boost::python;

int helloWorld(){
    cout << "Hello world!" << endl;
    return 0;
}

BOOST_PYTHON_MODULE(libhello) {
    def("hello_world", helloWorld);
}

编译命令:

g++ -fpic -shared -o libfoo.so -Wl,-soname,"libfoo.so" hello.cpp -I<path/to/python> -L/usr/local/lib  -lboost_python-py34

python 中包含import libfoo 时会出现以下错误:

ImportError: dynamic module does not define init function (PyInit_libfoo)

这是因为“libhello”和“libfoo”不匹配。

【讨论】:

  • 哇!这个小 sn-p 对我来说比大多数 Boost 文档更有帮助!
  • libemotion 名称从何而来?
【解决方案2】:

值得通知 - 如果为不同的 python 版本编译库,可能会出现同样的错误。例如,如果共享对象适用于 python 3,但您尝试从 python 2 导入模块。

【讨论】:

  • initfizzbuzz是python2的命名方案,python3需要PyInit_libfizzbuzz。因此,如果您知道您的库是为 python3 构建的并且您会收到错误消息。在最初的问题中,可能是一些 python2 解释器介入了。这就是 conda env 发生在我身上的事情。使用 sphinx 为我的模块构建文档时使用 python 3.6 和系统 python2.7。
  • 我也是这样。我已经使用 python3.6 编译了 python 包装器,并试图使用 python2.7 导入我的库。感谢您的评论!
【解决方案3】:

Python 不支持也不能支持任意 C 文件作为模块。您必须遵循某些约定才能让 Python 知道您的模块支持哪些功能。

为此,Python 将查找init&lt;name&gt; 函数,其中&lt;name&gt; 是模块名称。 Python 一直在寻找 initfizzbuzz 但没有找到,因此加载模块失败。

除了初始化器之外,您还需要提供详细说明可用函数的结构,并且您的函数需要将 Python 类型作为参数处理。 Python 为您提供了必要的实用程序函数和定义,使这变得足够简单。

我强烈建议您关注Extending and Embedding the Python Interpreter tutorial。它会教您使您的 fizzbuzz C 代码作为 Python 模块工作所需了解的一切。

【讨论】:

    【解决方案4】:

    做 python3 ./yourpythonscript

    而不是

    python ./yourpythonscript

    即使你有 python 别名为 python3

    名称必须与编译 boost 和 boost-python 时使用的名称完全相同: brew reinstall boost --with-python3 --without-python brew reinstall boost-python --with-python3 --without-python

    【讨论】:

    • 我遇到了和 OP 一样的问题,你的回答对我有用。
    【解决方案5】:

    您应该定义一个名为init_fizzbuzz 的函数,它应该包含初始化模块的代码。此函数还应调用Py_InitModule,以设置 Python 中 c 函数的绑定。如需更多信息,请查看this tutorial

    在你的情况下,你的代码应该适应这样的:

    static PyObject* py_fizzbuzz(PyObject* self, PyObject* args)
    {
        int value;
        if (!PyArg_ParseTuple(args, "i", &value))
            return NULL;
        for (int i=1; i <= n; i++){
            if (i % 3 == 0 && i % 5 ==0){
                printf("fizzbuzz %d \n", i);
                }
            else if (i % 3 == 0){
                printf("fizz %d \n", i);
                }
            else if(i % 5 == 0){
                printf("buzz %d \n", i);
                }
            }
    
        // Return value.
        return Py_BuildValue("i", 0);
    
    }
    
    // Mapping between python and c function names. 
    static PyMethodDef fizzbuzzModule_methods[] = {
        {"fizzbuzz", py_fizzbuzz, METH_VARARGS},
        {NULL, NULL}
        };
    
    // Module initialisation routine.
    void init_fizzbuzz(void)
    {
        // Init module.
        (void) Py_InitModule("fizzbuzz", fizzbuzzModule_methods);
    
    }
    

    【讨论】:

    • −1import _fizzbuzzyieldsdynamic module not initialised properlyinitfizzbuzz更正为init_fizzbuzz
    【解决方案6】:

    如果您使用 python 3,那么您需要对您的代码进行以下更改,

    static struct PyModuleDef fizzbuzzModuleDef =
    {
        PyModuleDef_HEAD_INIT,
        "fizzbuzz", /* name of module */
        "",          /* module documentation, may be NULL */
        -1,          /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
        fizzbuzzModule_methods
    };
    
    PyMODINIT_FUNC PyInit_exmod(void) {
        return PyModule_Create(&fizzbuzzModuleDef);
    }
    

    【讨论】:

      猜你喜欢
      • 2015-03-18
      • 2011-06-29
      • 2017-07-21
      • 1970-01-01
      • 2015-09-22
      • 2016-03-21
      • 1970-01-01
      • 2011-02-02
      相关资源
      最近更新 更多