如何构建 Python C 扩展,以便我可以从模块中导入它

Posted

技术标签:

【中文标题】如何构建 Python C 扩展,以便我可以从模块中导入它【英文标题】:How to build a Python C Extension so I can import it from a module 【发布时间】:2012-08-23 18:17:13 【问题描述】:

我有一个包含许多子模块的 Python 项目,这些子模块是用 distutils 打包的。我想在 C 中构建一些 Python 扩展以存在于其中一些子模块中,但我不明白如何让 Python 扩展存在于子模块中。以下是我正在寻找的最简单的示例:

这是我的 Python 扩展 c_extension.c

#include <Python.h>

static PyObject *
get_answer(PyObject *self, PyObject *args)

    return Py_BuildValue("i", 42);


static PyMethodDef Methods[] = 
    "get_answer",  get_answer, METH_VARARGS, "The meaning of life.",
    NULL, NULL, 0, NULL
;

PyMODINIT_FUNC
initc_extension(void) 
  (void) Py_InitModule("c_extension", Methods);

这是一个有效的setup.py

from distutils.core import setup
from distutils.extension import Extension

setup(name='c_extension_demo',
      ext_modules = [Extension('c_extension', sources = ['c_extension.c'])])

在 virtualenv 中安装后,我可以这样做:

>>> import c_extension
>>> c_extension.get_answer()
42

但我想让c_extension 存在于一个子模块中,比如foo.bar。我需要在此管道中进行哪些更改才能使 Python shell 中的行为如下所示:

>>> import foo.bar.c_extension
>>> foo.bar.c_extension.get_answer()
42

【问题讨论】:

相关:***.com/q/12097755/7954504 对于python &gt;= 3.10distutils 已弃用,详情请参阅my answer in another thread 【参考方案1】:

只是改变

Extension('c_extension', ...)

Extension('foo.bar.c_extension', ...)

像往常一样,foobar 目录中的每个目录中都需要 __init__.py 文件。要将这些与 setup.py 中的模块打包在一起,您需要添加

packages = ['foo', 'foo.bar'],

到你的 setup() 调用,你将需要目录结构

setup.py
foo/
    __init__.py
    bar/
        __init__.py

在您的源目录中。

【讨论】:

感谢您的回答,但这对我不起作用。我创建了foo/bar 目录,每个目录都带有__init__.py,并在设置命令中添加了foo.bar. 前缀,但在python shell 中会发生这种情况:>>> import foo.bar.c_extension Traceback(最近一次调用最后一次):文件“”,第 1 行,在 ImportError: No module named c_extension 您使用的是什么版本的 Python?我正在测试 2.7.3。 不要从您的源目录进行测试。这将尝试从没有 c_extension 的源目录中的 foo/bar 导入。 哦,对了。就是这样。感谢您的帮助!

以上是关于如何构建 Python C 扩展,以便我可以从模块中导入它的主要内容,如果未能解决你的问题,请参考以下文章

尝试编译C扩展模块时缺少Python.h

如何使用 distutils 安装 Python 扩展模块?

Python 模块应该如何使用代码生成?

从 C 函数构建 PyObject*?

您将如何安装 python 模块/包,以便我的脚本可以使用 pypy3 而不是 Python3 运行? ImportError:没有命名的模块

如何构建和分发依赖于第三方 libFoo.so 的 Python/Cython 包