如何在 Python 模块中嵌套 c-api 扩展并在该模块中使用它们?
How to nest c-api extensions in a Python module and use them in that module?
我想创建一个名为 "mypack" 的 Python 3 包,可以使用 pip 安装。它有一些 c 扩展和一些调用这些扩展的 python 代码。这是我的目录结构:
setup.py
mypack/__init__.py
mypack/mypack.py
foopkg/foo.cpp
setup.py 文件具有以下代码:
from setuptools import setup, Extension
PACKAGE_NAME = 'mypack'
module = Extension('foo',
language = "c++",
sources = ['foopkg/foo.cpp'])
setup(name=PACKAGE_NAME,
version='1.0',
packages=[PACKAGE_NAME],
ext_package=PACKAGE_NAME,
ext_modules=[module],
include_package_data=True)
我从另一个相关问题中改编了这段代码,其中用户希望像我一样使用 mypack.xxx
之类的东西导入扩展。在 c-api 扩展中,我已经成功编译它并使其作为一个独立的扩展模块工作,但我无法将它合并到一个更大的包中。它定义了两个函数 make_array
和 print_array
。为简洁起见,我删除了函数代码,只包含了 Python 需要的内容:
...
static PyMethodDef FooMethods[] = {
{ "make_array", make_array, METH_VARARGS, "Put number in array"},
{ "print_array", print_array, METH_VARARGS, "Print number from array"},
{ NULL, NULL, 0, NULL}
};
static struct PyModuleDef foomodule = {
PyModuleDef_HEAD_INIT,
"foo",
"Make/Print array",
-1,
FooMethods
};
PyMODINIT_FUNC PyInit_foo(void)
{
return PyModule_Create(&foomodule);
}
我希望能够在包中导入此扩展以使用它(这是 mypack.py
):
import mypack.make_array
import mypack.print_array
def dostuff():
array = make_array(10)
print_array(array)
最后,我的 __init__.py
文件包含 from .mypack import dostuff
。
但是,当我使用 pip 安装并尝试 运行 导入 mypack
的测试脚本时,它会抱怨 mypack.py
中的导入,我是否使用 foo.xx
或 mypack.xx
。我已经构建了其他具有嵌套结构的包,这些包使用模块中其他 python 文件的代码,使用 __init__.py
并使用导入。但是我对如何使用 c-extensions 做到这一点感到有点困惑。
模块是从 C 编译的这一事实对您如何编写 import 语句没有影响。该行...
import mypack.make_array
尝试导入在名为 "mypack" 的包中找到的名为 "make_array" 的模块。那不是你所拥有的。您在名为 "mypack" 的包中有一个名为 "foo" 的模块,并且该模块中有两个名为 "make_array" 和 "print_array."
的对象(方法)
如果您从 __init__.py
中删除所有内容并使其以这种方式工作,那就简单多了。如果您想改进 import 语句的语法,您可以稍后将内容添加到 init 文件中。你想要...
from mypack.foo import make_array, print_array
或
import mypack.foo as MYPACK
在第一种情况下,方法现在位于全局命名空间中;在第二种情况下,您以 MYPACK.make_array
和 MYPACK.print_array
.
访问它们
此外,我还发现命名您的 C 扩展文件 mypack
以及命名您的 python 文件 mypack.py
的问题。中只能有一个具有该名称的模块
一袋。一种解决方案是在 C 文件名前加一个下划线前缀。然后在 mypack.py 你写,例如...
from ._mypack import make_array
这将 make_array
放入 myarray
的命名空间,客户端代码不必知道或关心它是用 C 编写的。
我想创建一个名为 "mypack" 的 Python 3 包,可以使用 pip 安装。它有一些 c 扩展和一些调用这些扩展的 python 代码。这是我的目录结构:
setup.py
mypack/__init__.py
mypack/mypack.py
foopkg/foo.cpp
setup.py 文件具有以下代码:
from setuptools import setup, Extension
PACKAGE_NAME = 'mypack'
module = Extension('foo',
language = "c++",
sources = ['foopkg/foo.cpp'])
setup(name=PACKAGE_NAME,
version='1.0',
packages=[PACKAGE_NAME],
ext_package=PACKAGE_NAME,
ext_modules=[module],
include_package_data=True)
我从另一个相关问题中改编了这段代码,其中用户希望像我一样使用 mypack.xxx
之类的东西导入扩展。在 c-api 扩展中,我已经成功编译它并使其作为一个独立的扩展模块工作,但我无法将它合并到一个更大的包中。它定义了两个函数 make_array
和 print_array
。为简洁起见,我删除了函数代码,只包含了 Python 需要的内容:
...
static PyMethodDef FooMethods[] = {
{ "make_array", make_array, METH_VARARGS, "Put number in array"},
{ "print_array", print_array, METH_VARARGS, "Print number from array"},
{ NULL, NULL, 0, NULL}
};
static struct PyModuleDef foomodule = {
PyModuleDef_HEAD_INIT,
"foo",
"Make/Print array",
-1,
FooMethods
};
PyMODINIT_FUNC PyInit_foo(void)
{
return PyModule_Create(&foomodule);
}
我希望能够在包中导入此扩展以使用它(这是 mypack.py
):
import mypack.make_array
import mypack.print_array
def dostuff():
array = make_array(10)
print_array(array)
最后,我的 __init__.py
文件包含 from .mypack import dostuff
。
但是,当我使用 pip 安装并尝试 运行 导入 mypack
的测试脚本时,它会抱怨 mypack.py
中的导入,我是否使用 foo.xx
或 mypack.xx
。我已经构建了其他具有嵌套结构的包,这些包使用模块中其他 python 文件的代码,使用 __init__.py
并使用导入。但是我对如何使用 c-extensions 做到这一点感到有点困惑。
模块是从 C 编译的这一事实对您如何编写 import 语句没有影响。该行...
import mypack.make_array
尝试导入在名为 "mypack" 的包中找到的名为 "make_array" 的模块。那不是你所拥有的。您在名为 "mypack" 的包中有一个名为 "foo" 的模块,并且该模块中有两个名为 "make_array" 和 "print_array."
的对象(方法)如果您从 __init__.py
中删除所有内容并使其以这种方式工作,那就简单多了。如果您想改进 import 语句的语法,您可以稍后将内容添加到 init 文件中。你想要...
from mypack.foo import make_array, print_array
或
import mypack.foo as MYPACK
在第一种情况下,方法现在位于全局命名空间中;在第二种情况下,您以 MYPACK.make_array
和 MYPACK.print_array
.
此外,我还发现命名您的 C 扩展文件 mypack
以及命名您的 python 文件 mypack.py
的问题。中只能有一个具有该名称的模块
一袋。一种解决方案是在 C 文件名前加一个下划线前缀。然后在 mypack.py 你写,例如...
from ._mypack import make_array
这将 make_array
放入 myarray
的命名空间,客户端代码不必知道或关心它是用 C 编写的。