Python 导入错误:动态模块未定义 init 函数 (initfizzbuzz)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24226001/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 04:16:01  来源:igfitidea点击:

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

pythoncpython-c-api

提问by SamuraiT

I tried to compile fizzbuzz.c, in order to import it by python. For building fizzbuzz.c,I used python setup.py build_ext -i.

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

After building it, I tried to import fizzbuzz.cbut the error below occurred. How can I solve this problem ?

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

Error

错误

>>> 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],
)

采纳答案by Martijn Pieters

Python doesn't and cannot support arbitrary C files as modules. You'll have to follow certain conventions to let Python know what functions your module supports.

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

To do so, Python will look for a init<name>function, where <name>is the module name. Python was looking for initfizzbuzzbut failed to find it, so loading the module failed.

为此,Python 将查找一个init<name>函数,其中<name>是模块名称。Python 正在寻找initfizzbuzz但没有找到它,因此加载模块失败。

Apart from an initialiser, you also need to provide a structure detailing what functions are available, and your function will need to handle Python types as arguments. Python provides you with the necessary utility functions and defines to make that easy enough.

除了初始化程序之外,您还需要提供一个详细说明哪些函数可用的结构,并且您的函数需要将 Python 类型作为参数进行处理。Python 为您提供了必要的实用函数,并定义了使这足够容易的定义。

I strongly urge you follow the Extending and Embedding the Python Interpreter tutorial. It teaches you everything you need to know to make your fizzbuzzC code work as a Python module.

我强烈建议您遵循扩展和嵌入 Python 解释器教程。它教给您使fizzbuzzC 代码作为 Python 模块工作所需的一切知识。

回答by lackadaisical

You should define a function named init_fizzbuzz, that should contain the code to initialize the module. This function should also call Py_InitModule, to setup the bindings for the c functions in Python. For further info, check out this tutorial.

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

In yor case, your code should be adapted to something like this:

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

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);

}

回答by philosopher

The error also occurs, when using boost::python, if the module name is different to the compiled .so file name. For example:

当使用boost::python 时,如果模块名称与编译的 .so 文件名不同,也会发生错误。例如:

hello.cpp

你好.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);
}

compilation command:

编译命令:

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

When including in pythonwith import libfoothe following error occurs:

包括当蟒蛇import libfoo出现以下错误:

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

This is because of "libhello" and "libfoo" do not match.

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

回答by Ivan Klass

Worth notify - same error can occur if library is compiled for different python version. For example, if shared object is for python 3, but you try to import module from python 2.

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

回答by kar

If you use python 3 then you need to have the following changes on your code,

如果您使用 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);
}

回答by Aditya Mittal

do python3 ./yourpythonscript

做 python3 ./yourpythonscript

instead of

代替

python ./yourpythonscript

蟒蛇./你的pythonscript

even if you have python aliased as python3

即使你将 python 别名为 python3

The name must be exact with which you compile boost and boost-python: brew reinstall boost --with-python3 --without-python brew reinstall boost-python --with-python3 --without-python

名称必须与您编译 boost 和 boost-python 的名称完全相同: brew restart boost --with-python3 --without-python brew restart boost-python --with-python3 --without-python