简体   繁体   English

如何将c-api扩展嵌套在Python模块中并在该模块中使用它们?

[英]How to nest c-api extensions in a Python module and use them in that module?

I want to create a Python 3 package called "mypack" that can be installed with pip. 我想创建一个名为“ mypack”的Python 3程序包,可以通过pip进行安装。 It has some c-extensions and some python code that calls those extensions. 它具有一些c扩展名和一些调用这些扩展名的python代码。 Here is my directory structure: 这是我的目录结构:

setup.py
mypack/__init__.py
mypack/mypack.py
foopkg/foo.cpp

The setup.py file has the following code: 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)

I adapted this code from another related question where the user wanted to import the extensions using something like mypack.xxx , as I do. 我从另一个相关问题改编了此代码,在该问题中,用户希望像mypack.xxx这样导入扩展名,就像我一样。 In the c-api extension, I have successfully compiled it and made it work as a stand-alone extension module, but I am having trouble incorporating it into a larger package. 在c-api扩展中,我已经成功地对其进行了编译,并使它可以作为独立的扩展模块使用,但是在将其合并到较大的程序包中时遇到了麻烦。 It defines two functions make_array and print_array . 它定义了两个函数make_arrayprint_array For brevity I removed the function code and just included the stuff that Python needs: 为了简洁起见,我删除了功能代码,只包含了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);
}

I want to be able to import this extension within the package to use it (this is mypack.py ): 我希望能够在包中导入此扩展名以使用它(这是mypack.py ):

import mypack.make_array
import mypack.print_array

def dostuff():
    array = make_array(10)
    print_array(array)

Lastly, my __init__.py file contains from .mypack import dostuff . 最后,我的__init__.py文件包含from .mypack import dostuff文件。

However, when I install with pip, and try to run a test script that imports mypack it complains about the imports in mypack.py , whether I use foo.xx or mypack.xx . 然而,当我安装与点子,并尝试运行测试脚本,进口mypack它抱怨在进口mypack.py ,不管我用foo.xxmypack.xx I have built other packages with a nested structure that use code from other python files in the module using __init__.py and using imports. 我使用嵌套结构构建了其他软件包,这些软件包使用__init__.py和导入功能使用模块中其他python文件的代码。 But I am a bit baffled about how to do this with c-extensions. 但是我对如何使用c扩展名感到困惑。

The fact that the module is compiled from C makes no difference to how you write the import statement. 从C编译模块的事实与编写import语句的方式没有区别。 The line... 线...

import mypack.make_array

tries to import a module named "make_array" found in a package named "mypack". 尝试导入在名为“ mypack”的程序包中找到的名为“ make_array”的模块。 That's not what you have. 那不是你所拥有的。 You have a module named "foo" in a package named "mypack", and two objects (methods) in that module named "make_array" and "print_array." 您在名为“ mypack”的程序包中有一个名为“ foo”的模块,并且在该模块中有两个名为“ make_array”和“ print_array”的对象(方法)。

It's much simpler if you remove everything from __init__.py and make it work that way. 如果从__init__.py删除所有内容并使其以这种方式工作,则要简单得多。 You can add stuff to the init file later if you want to improve the syntax of your import statements. 如果您想改善import语句的语法,可以稍后将内容添加到init文件中。 You want... 你要...

from mypack.foo import make_array, print_array

or 要么

import mypack.foo as MYPACK

In the first case the methods are now in the global namespace; 在第一种情况下,这些方法现在位于全局名称空间中。 in the second case you access them as MYPACK.make_array and MYPACK.print_array . 在第二种情况下,您可以使用MYPACK.make_arrayMYPACK.print_array访问它们。

Also I see a problem with naming your C-extension file mypack and also naming your python file mypack.py . 我也看到命名您的C扩展名文件mypack和命名您的python文件mypack.py There can be only one module with that name in a package. 包中只能有一个具有该名称的模块。 One solution is to prefix an underscore to the C file name. 一种解决方案是在C文件名前加下划线。 Then in mypack.py you write, for example... 然后例如在mypack.py中编写...

from ._mypack import make_array

This puts make_array into the namespace of myarray , and client code doesn't have to know, or care, that it's written in C. 这会将make_array放入myarray的命名空间中,并且客户端代码不必知道或不在乎它是用C编写的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM