我有一个用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
>>>
该模块是用this simple code构建的,它是用于python2的。我还有same example for python3
这里有两个问题:第一,
Py_InitModule
和朋友希望创建导入的模块。提示是您传递给它的字符串不是模块的完全限定名:Python使用它已经知道的名称来确定在sys.modules
中放置新对象的位置。但是,您可以使用完全限定的名称;其他魔法属性(如__file__
)将具有正确的值第二个问题是需要在包含模块上设置属性
light
,以便from
导入工作同时,没有理由使用单独的初始化函数(解释器将永远不会调用该函数),将它们结合使用可以避免以后需要恢复指向模块的指针:
也就是说,
sysipc
仍然不是一个合适的包:至少,它缺少__path__
。如果这很重要,您可能更喜欢使用真实(如果更复杂)包体系结构的MEE's answer从https://www.python.org/dev/peps/pep-0489/#multiple-modules-in-one-library引用:
换句话说,您需要按如下方式重新构造项目
importlib
,以便能够在sysipc
包中找到子模块light
:light.so
和sysipc.so
之间的硬链接可以通过以下方式创建:然后在
company/dept/sys/sysipc/__init__.py
中,使用以下方法从sysipc.so
导入所有符号:此外,对于Python2,需要将子模块C扩展init函数的名称从
init_sysipc_light
更改为init_light
,对于Python3,需要将子模块C扩展init函数的名称从PyInit_sysipc_light
更改为PyInit_light
,因为importlib
通过从动态模块中查找导出的PyInit_<module name>
来加载模块,并且这里的模块名称仅为light
,即。,父包前缀不是(子)模块名称的一部分以下是扩展代码(Python3)和两个用于测试的函数:
test.py:
输出:
相关问题 更多 >
编程相关推荐