子模块的python导入路径(如果放在名称空间包中)

泛光灯

我有一个用C编写的python模块,它有一个主模块和一个子模块(名称带有点,不确定是否可以将其称为真实子模块):

PyMODINIT_FUNC initsysipc(void) {
    PyObject *module = Py_InitModule3("sysipc", ...);
    ...
    init_sysipc_light();
}

static PyTypeObject FooType = { ... };
PyMODINIT_FUNC init_sysipc_light(void) {
    PyObject *module = Py_InitModule3("sysipc.light", ...);
    ...
    PyType_Ready(&FooType);
    PyModule_AddObject(module, "FooType", &FooType);
}

该模块编译为sysipc.so,当我将其放在当前目录中时,以下导入可以正常工作:

import sysipc
import sysipc.light
from sysipc.light import FooType

问题是我想将此模块放在名称空间包中,文件夹结构如下所示:

company/
company/__init__.py
company/dept/
company/dept/__init__.py
company/dept/sys/
company/dept/sys/__init__.py
company/dept/sys/sysipc.so

所有这三个都__init__.py包括标准setuptool导入行:

__path__ = __import__('pkgutil').extend_path(__path__, __name__)

在当前目录中,以下导入无效:

from company.dept.sys import sysipc;
from company.dept.sys.sysipc.light import FooType;

sysipc.light在这种情况下,应如何导入模块定义的类型和方法

==================================

用实际错误更新:

我已经sysipc.so构建好了,如果我在当前目录中以此模块运行python,则导入将按预期进行:

[root@08649fea17ef 2]# python2
Python 2.7.18 (default, Jul 20 2020, 00:00:00)
[GCC 10.1.1 20200507 (Red Hat 10.1.1-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sysipc
>>> import sysipc.light
>>>

但是,如果我将其放入命名空间文件夹中,则如下所示:

company/
company/__init__.py
company/dept
company/dept/__init__.py
company/dept/sys
company/dept/sys/sysipc.so
company/dept/sys/__init__.py

导入子模块将不起作用:

>>> from company.dept.sys import sysipc
>>> from company.dept.sys import sysipc.light
  File "<stdin>", line 1
    from company.dept.sys import sysipc.light
                                   ^
SyntaxError: invalid syntax
>>> from company.dept.sys.sysipc import light
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name light
>>>

该模块使用此简单代码构建,适用于python2。我也有python3的相同示例

沿

https://www.python.org/dev/peps/pep-0489/#multiple-modules-in-one-library引用

为了在一个共享库中支持多个Python模块,该库可以导出与库文件名相对应的符号之外的其他PyInit *符号

请注意,该机制目前只能用于加载额外的模块,而不能用于找到它们(这是加载程序机制的限制,此PEP不会尝试对其进行修改。)...

换句话说,您需要按如下所示重组项目,importlib以便能够lightsysipc包中找到子模块

company/__init__.py
company/dept/__init__.py
company/dept/sys/__init__.py
company/dept/sys/sysipc/__init__.py
company/dept/sys/sysipc/sysipc.so
company/dept/sys/sysipc/light.so -> sysipc.so  # hardlink

light.so之间的硬链接sysipc.so可以通过以下方式创建:

ln company/dept/sys/sysipc/sysipc.so company/dept/sys/sysipc/light.so

然后在company/dept/sys/sysipc/__init__.pysysipc.so使用以下命令导入所有符号

from .sysipc import *

此外,您需要将子模块C扩展初始化函数的名称从init_sysipc_light更改init_light为Python2,或从PyInit_sysipc_light更改PyInit_light为Python3,因为importlib通过查找PyInit_<module name>从动态模块导出的模块来加载模块,并且此处的模块名称仅为light,即父程序包前缀不是(子)模块名称的一部分。

这是扩展代码(Python3)和一些测试功能:

#include <Python.h>

PyObject *sysipc_light_foo(PyObject *self, PyObject *args) {
  printf("[*] sysipc.light.foo\n");
  return PyLong_FromLong(0);
}

static PyMethodDef sysipc_light_methods[] = {
    {"foo", (PyCFunction)sysipc_light_foo, METH_VARARGS, "sysipc.light.foo function"},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef sysipc_light_module = {
    PyModuleDef_HEAD_INIT,
    "sysipc.light",
    "sysipc child module",
    -1,
    sysipc_light_methods
};

PyMODINIT_FUNC PyInit_light(void)
{
    PyObject *module = NULL;

    module = PyModule_Create(&sysipc_light_module);

    return module;
}

PyObject *sysipc_bar(PyObject *self, PyObject *args) {
  printf("[*] sysipc.bar\n");
  return PyLong_FromLong(0);
}

static PyMethodDef sysipc_methods[] = {
    {"bar", (PyCFunction)sysipc_bar, METH_VARARGS, "sysipc.bar function"},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef sysipc_module = {
    PyModuleDef_HEAD_INIT,
    "sysipc",
    "sysipc parent module",
    -1,
    sysipc_methods
};

PyMODINIT_FUNC PyInit_sysipc(void)
{
    PyObject *module = NULL;

    module = PyModule_Create(&sysipc_module);

    PyInit_light();

    return module;
}

test.py:

#!/usr/bin/env python3

from company.dept.sys import sysipc
from company.dept.sys.sysipc import light

sysipc.bar() 
light.foo()

输出:

[*] sysipc.bar
[*] sysipc.light.foo

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章