合成子模块:来自A导入B(ok)与导入A.B(错误)?

时间:2012-06-16 12:03:11

标签: python boost-python python-module synthetic

我有一个模块modA,其中包含一个合成子模块modB(使用PyModule_New创建);现在导入模块:

  1. from modA import modB没关系
  2. import modA.modB失败。
  3. 我错过了什么?

    • modA.cpp(使用boost::python,但它很可能与python的纯c-API相同):

      #include<boost/python.hpp>
      namespace py=boost::python;
      
      BOOST_PYTHON_MODULE(modA){
         py::object modB=py::object(py::handle<>(PyModule_New("modB")));
         modB.attr("__file__")="<synthetic>";
         py::scope().attr("modB")=modB;
      };
      
    • 编译(g ++而不是clang ++的工作方式相同)

      clang++ -o modA.so modA.cpp -fPIC -shared  -lboost_python `pkg-config python --cflags --libs`
      
    • test.py:

      import sys
      sys.path.append('.')
      from modA import modB
      import modA.modB
      
    • python test.py(注意第一次导入很好,第二次导致失败):

      Traceback (most recent call last):
        File "test.py", line 4, in <module>
          import modA.modB
      ImportError: No module named modB
      

3 个答案:

答案 0 :(得分:1)

感谢this answer,我找到了解决方案,该解决方案包含在sys.modules['modA.modB']=modB中,但在模块初始化函数中用c ++编写:

#include<boost/python.hpp>
namespace py=boost::python;

BOOST_PYTHON_MODULE(modA){
   py::object modB=py::object(py::handle<>(PyModule_New("modA.modB")));
   modB.attr("__file__")="<synthetic>";
   py::scope().attr("modB")=modB;

   // this was the missing piece: sys.modules['modA.modB']=modB
   py::extract<py::dict>(py::getattr(py::import("sys"),"modules"))()["modA.modB"]=modB;
};

答案 1 :(得分:1)

这是我使用的模式,希望它能改善以前的答案......

module.h中:

...
#define STR(str) #str
#define MAKE_SUBMODULE(mod, submod) object submod##_module(handle<>(borrowed(PyImport_AddModule(STR(mod.submod)))));\
scope().attr(STR(submod)) = submod##_module;\
scope submod##_scope = submod##_module;\
...
export_submodule();
...

module.cpp:

BOOST_PYTHON_MODULE(modulename)
{
    export_submodule();
}

submodule.cpp:

export_submodule()
{
    // create submodule
    MAKE_SUBMODULE(modulename, submodulename)

    // all code below is now in submodule's scope
    ...
}

&#34;生成&#34;代码如下所示:

object submodulename_module(handle<>(borrowed(PyImport_AddModule("modulename.submodulename"))));
scope().attr("submodulename") = submodulename_module;
scope submodulename_scope = submodulename_module;

它看起来类似于eudoxos答案,但差异似乎很详细:我使用PyImportNew()而不是PyImportAdd()。因此,我不需要最后一行来使from module.submodule import *语句正常工作。

答案 2 :(得分:0)

modB不是文件(即模块),而是modA中的某个对象,因此无法导入。

您可能希望看到Python's modules docs