2

我在使用简单的 C 文件扩展 python 时遇到问题。

hello.c 源代码:

#include <Python.h>

static PyObject* say_hello(PyObject* self, PyObject* args)
{
    const char* name;

    if (!PyArg_ParseTuple(args, "s", &name))
        return NULL;

    printf("Hello %s!\n", name);

    Py_RETURN_NONE;
}

static PyMethodDef HelloMethods[] =
{
     {"say_hello", say_hello, METH_VARARGS, "Greet somebody."},
     {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
inithello(void)
{
     (void) Py_InitModule("hello", HelloMethods);
}

设置.py:

from distutils.core import setup, Extension

module1 = Extension('hello', sources = ['hello.c'])

setup (name = 'PackageName',
       version = '1.0',
       packages=['hello'],
       description = 'This is a demo package',
       ext_modules = [module1])

我还在文件夹“hello”中创建了空文件“__init__.py”。

调用“python setup.py build”后,我可以导入你好,但是当我尝试使用“hello.say_hello()”时,我遇到了错误:

回溯(最后一次调用):文件“<stdin>”,第 1 行,在 AttributeError:'module' 对象没有属性 'say_hello'

如果有人可以帮助我找到解决方案,我将不胜感激。

谢谢

4

1 回答 1

1

您正在导入包而不是扩展名:

$python2 hello_setup.py build
running build
running build_py
# etc.
$cd build/lib.linux-x86_64-2.7/
$ls
hello  hello.so
$python
Python 2.7.4 (default, Apr 19 2013, 18:28:01) 
[GCC 4.7.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import hello
>>> hello
<module 'hello' from 'hello/__init__.py'>

如果要导入扩展名,hello.so则必须重命名它,或者将其放在包下。在这种情况下,您可以使用from hello import hello它来导入它:

$mv hello.so hello
$python2
Python 2.7.4 (default, Apr 19 2013, 18:28:01) 
[GCC 4.7.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from hello import hello
>>> hello
<module 'hello.hello' from 'hello/hello.so'>
>>> hello.say_hello("World!")
Hello World!!

我看不出有一个只包含一个扩展模块的包的原因。我只是使用更简单的设置摆脱了这个包:

from distutils.core import setup, Extension

module1 = Extension('hello', sources=['hello.c'])

setup(name='MyExtension',
       version='1.0',
       description='This is a demo extension',
       ext_modules=[module1])

这只会生成hello.so库,您可以简单地执行以下操作:

>>> import hello

导入扩展。

一般建议:避免使用多个具有相同名称的模块/包。有时很难判断导入了哪个模块(如您的情况)。此外,当使用不同的名称而不是导入错误的模块并得到奇怪的错误时,您会看到ImportError是否有问题,它指出了究竟缺少什么。

于 2013-08-27T12:27:55.710 回答