python 3.x C扩展模块和子模块 [英] python 3.x C extension module and submodule

查看:114
本文介绍了python 3.x C扩展模块和子模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当模块具有子模块时,如何为python 3.x进行C扩展?例如,我有一个名为pet.c的文件:

How do I make a C extension for python 3.x when a module has sub-modules? For example, I have a file called pet.c:

#include <Python.h>

PyObject* CatMeow(PyObject* self) {
    return PyUnicode_FromString( ">*<" );
}

static PyMethodDef CatFunctions[] = {
    {(char*) "meow", (PyCFunction) CatMeow, METH_NOARGS, NULL},
    {NULL, NULL, 0, NULL}
};

static PyModuleDef CatDef = {
    PyModuleDef_HEAD_INIT, "cat", "cat ext", -1, CatFunctions,
    NULL, NULL, NULL, NULL
};

PyMODINIT_FUNC PyInit_cat(void) {
    return PyModule_Create(&CatDef);
}

static PyModuleDef PetDef = {
    PyModuleDef_HEAD_INIT, "pet", "pet ext", -1, NULL,
    NULL, NULL, NULL, NULL
};

PyMODINIT_FUNC PyInit_pet(void) {
    PyObject* p = PyModule_Create(&PetDef);
    PyObject* c = PyInit_cat();
    Py_INCREF(c);
    PyModule_AddObject( p, "cat", c );
    return p;
}

当我使用以下setup.py构建它时:

When I build it with the following setup.py:

from distutils.core import setup, Extension

setup( 
    name='pet', 
    version='0.0', 
    ext_modules=[Extension('pet', ['pet.c'])]
)

我可以看到

>>> import pet
>>> pet.cat.meow()
'>*<'

>>> from pet import cat
>>> cat.meow()
'>*<'

这是预期的,但是当我尝试

which is as intended, but when I try

>>> from pet.cat import meow

我有一个ModuleNotFoundError,说……没有名为"pet.cat"的模块;'pet'不是一个包,如果我尝试

I have a ModuleNotFoundError saying ... No module named 'pet.cat'; 'pet' is not a package, and if I try

>>> from pet import cat
>>> from cat import meow

我有一个ModuleNotFoundError,说……没有名为"cat"的模块.但是如果我检查猫的类型

I have a ModuleNotFoundError saying ... No module named 'cat'. But if I check the type of cat

>>> type(cat)
<class 'module'>

这是一个模块.

我如何进行这项工作?将模块对象添加到另一个在python 2.7中正常工作的模块中.由于绝对导入样式,它不应该在python3中工作吗?还是我必须按照PEP 489中的描述进行多阶段初始化?

How do I make this work? Adding a module object to another module used to work well in python 2.7. Is it not supposed to work in python3 due to absolute import style? Or do I have to work with multi-phase initialisation as described in PEP 489?

推荐答案

关于第一个错误,该错误抱怨pet不是包装.如果pet仅用于为cat提供父母,则有一种简单的方法可以将其变成包:从pet.c中删除所有与pet相关的代码,并在setup.py

Regarding the first error which complains about pet not being a package. If pet is there only to provide a parent for cat, there is an easy way to turn it into a package: remove all the pet related code from pet.c and use ext_package in setup.py

from distutils.core import setup, Extension

setup( 
    name = 'pet',
    version = '0.0',
    ext_package = 'pet',
    ext_modules = [Extension('cat', ['pet.c'])]
)

运行上面的命令将创建一个名为"pet"的目录和一个名称以"cat"开头的共享库.这有效地创建了一个名称空间包-有两种类型的包:常规和名称空间,后者是不需要__init__.py的一种(有关详细信息,请参阅PEP 420).从宠物外面,您可以做

Running the above will create a directory called 'pet' and a shared library of which name starts with 'cat'. This effectively creates a namespace package -- there are two types of packages, regular and namespace, and the latter is the one without requiring __init__.py (see PEP 420 for details). From outside of pet, you can do

>>> from pet import cat
>>> from pet.cat import meow 
>>> meow()
'>*<'
>>> cat.meow()
'>*<'

之所以无法从cat导入喵中进行,是因为模块的标准名称是'pet.cat'而不是'cat',您可以从cat .__ name__进行确认.如果您在pet目录中运行解释器,则可以从cat import meow中进行.

The reason you can't do from cat import meow is because the fully qualified name of the module is 'pet.cat' not 'cat', which you can confirm it from cat.__name__. If you are running the interpreter inside of the directory pet, then you can do from cat import meow.

这篇关于python 3.x C扩展模块和子模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆